diff --git a/CMakeLists.txt b/CMakeLists.txt
index e320fafc..c480300f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -76,6 +76,11 @@ set(USE_PCH FALSE CACHE BOOL "Use shared precompiled headers")
set(DISABLE_TOR FALSE CACHE BOOL "Disable TOR library(and related tor-connect submodule)")
set(TESTNET FALSE CACHE BOOL "Compile for testnet")
set(BUILD_GUI FALSE CACHE BOOL "Build qt-daemon")
+set(USE_BITCOIN_SECP256K1_FOR_ECDSA FALSE CACHE BOOL "Use bitcoin-secp256k1 library for validating ECDSA(instead of OpenSSL)")
+if(NOT USE_BITCOIN_SECP256K1_FOR_ECDSA)
+ add_definitions(-DUSE_OPEN_SSL_FOR_ECDSA)
+endif()
+
include_directories(src contrib/eos_portable_archive contrib contrib/epee/include contrib/jwt-cpp/include ${OPENSSL_INCLUDE_DIR} "${CMAKE_BINARY_DIR}/version" "${CMAKE_BINARY_DIR}/contrib/zlib")
@@ -89,6 +94,7 @@ endif()
if(CAKEWALLET)
message("NOTICE: Building libraries for CAKEWALLET")
add_definitions(-DCAKEWALLET)
+ add_definitions(-DDISABLE_PFR_SERIALIZATION_SELFCHECK)
endif()
set(OPENSSL_USE_STATIC_LIBS TRUE) # link statically
@@ -240,8 +246,12 @@ if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
#set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "${__iphonesimulator_archs}")
#set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "${__iphonesimulator_archs}")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
- set(Boost_LIBRARY_DIRS "${Boost_LIBRARY_DIRS}/${CMAKE_ANDROID_ARCH_ABI}/")
- set(Boost_LIBRARIES "${Boost_LIBRARY_DIRS}libboost_system.a;${Boost_LIBRARY_DIRS}libboost_filesystem.a;${Boost_LIBRARY_DIRS}libboost_thread.a;${Boost_LIBRARY_DIRS}libboost_timer.a;${Boost_LIBRARY_DIRS}libboost_date_time.a;${Boost_LIBRARY_DIRS}libboost_chrono.a;${Boost_LIBRARY_DIRS}libboost_regex.a;${Boost_LIBRARY_DIRS}libboost_serialization.a;${Boost_LIBRARY_DIRS}libboost_atomic.a;${Boost_LIBRARY_DIRS}libboost_program_options.a")
+ if(CAKEWALLET)
+ find_package(Boost 1.71 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale)
+ else()
+ set(Boost_LIBRARY_DIRS "${Boost_LIBRARY_DIRS}/${CMAKE_ANDROID_ARCH_ABI}/")
+ set(Boost_LIBRARIES "${Boost_LIBRARY_DIRS}libboost_system.a;${Boost_LIBRARY_DIRS}libboost_filesystem.a;${Boost_LIBRARY_DIRS}libboost_thread.a;${Boost_LIBRARY_DIRS}libboost_timer.a;${Boost_LIBRARY_DIRS}libboost_date_time.a;${Boost_LIBRARY_DIRS}libboost_chrono.a;${Boost_LIBRARY_DIRS}libboost_regex.a;${Boost_LIBRARY_DIRS}libboost_serialization.a;${Boost_LIBRARY_DIRS}libboost_atomic.a;${Boost_LIBRARY_DIRS}libboost_program_options.a")
+ endif()
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fPIC")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fPIC")
elseif(APPLE)
@@ -259,7 +269,7 @@ include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/contrib/e
if(MINGW)
set(Boost_LIBRARIES "${Boost_LIBRARIES};ws2_32;mswsock")
elseif(NOT MSVC)
- if(NOT APPLE)
+ if(NOT APPLE AND NOT CAKEWALLET)
set(Boost_LIBRARIES "${Boost_LIBRARIES};")
if(STATIC)
message("NOTICE: Including static ICU libraries")
diff --git a/README.md b/README.md
index e4515a47..655e780a 100644
--- a/README.md
+++ b/README.md
@@ -15,10 +15,10 @@ Be sure to clone the repository properly:\
|--|--|--|--|
| gcc (Linux) | 5.4.0 | 9.4.0 | 12.3.0 |
| llvm/clang (Linux) | UNKNOWN | 7.0.1 | 8.0.0 |
-| [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2017 (15.9.30) | 2019 (16.11.34) | 2022 (17.9.5) |
+| [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2017 (15.9.30) | 2019 (16.11.34) | 2022 (17.11.5) |
| [XCode](https://developer.apple.com/downloads/) (macOS) | 12.3 | 14.3 | 15.2 |
| [CMake](https://cmake.org/download/) | 3.15.5 | 3.26.3 | 3.29.0 |
-| [Boost](https://www.boost.org/users/download/) | 1.70 | 1.70 | 1.84 |
+| [Boost](https://www.boost.org/users/download/) | 1.75 | 1.84 | 1.84 |
| [OpenSSL](https://www.openssl.org/source/) [(win)](https://slproweb.com/products/Win32OpenSSL.html) | 1.1.1n | 1.1.1w | 1.1.1w |
| [Qt](https://download.qt.io/archive/qt/) (*only for GUI*) | 5.8.0 | 5.11.2 | 5.15.2 |
@@ -52,10 +52,9 @@ Recommended OS versions: Ubuntu 20.04, 22.04 LTS.
3. Download and build Boost\
(Assuming you have cloned Zano into the 'zano' folder. If you used a different location for Zano, **edit line 4** accordingly.)
- curl -OL https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.bz2
- echo "430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 boost_1_70_0.tar.bz2" | shasum -c && tar -xjf boost_1_70_0.tar.bz2
- rm boost_1_70_0.tar.bz2 && cd boost_1_70_0
- patch -p0 < ../zano/utils/boost_1.70_gcc_8.patch || cd ..
+ curl -OL https://boostorg.jfrog.io/artifactory/main/release/1.84.0/source/boost_1_84_0.tar.bz2
+ echo "cc4b893acf645c9d4b698e9a0f08ca8846aa5d6c68275c14c3e7949c24109454 boost_1_84_0.tar.bz2" | shasum -c && tar -xjf boost_1_84_0.tar.bz2
+ rm boost_1_84_0.tar.bz2 && cd boost_1_84_0
./bootstrap.sh --with-libraries=system,filesystem,thread,date_time,chrono,regex,serialization,atomic,program_options,locale,timer,log
./b2 && cd ..
Make sure that you see "The Boost C++ Libraries were successfully built!" message at the end.
@@ -88,13 +87,13 @@ For instance, by adding the following lines to `~/.bashrc`
[*server version*]
- export BOOST_ROOT=/home/user/boost_1_70_0
+ export BOOST_ROOT=/home/user/boost_1_84_0
export OPENSSL_ROOT_DIR=/home/user/openssl
[*GUI version*]
- export BOOST_ROOT=/home/user/boost_1_70_0
+ export BOOST_ROOT=/home/user/boost_1_84_0
export OPENSSL_ROOT_DIR=/home/user/openssl
export QT_PREFIX_PATH=/home/user/Qt5.11.2/5.11.2/gcc_64
@@ -169,3 +168,14 @@ To build GUI application:
2. Revise building script, comment out unwanted steps and run it: `utils/build_script_mac_osx.sh`
3. The application should be here: `/buid_mac_osx_64/release/src`
+
+
+
+## Supporting project/donations
+
+ZANO @dev
+BTC bc1qpa8w8eaehlplfepmnzpd7v9j046899nktxnkxp
+BCH qqgq078vww5exd9kt3frx6krdyznmp80hcygzlgqzd
+ETH 0x206c52b78141498e74FF074301ea90888C40c178
+XMR 45gp9WTobeB5Km3kLQgVmPJkvm9rSmg4gdyHheXqXijXYMjUY48kLgL7QEz5Ar8z9vQioQ68WYDKsQsjAEonSeFX4UeLSiX
+
diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt
index c1a5535f..842f905c 100644
--- a/contrib/CMakeLists.txt
+++ b/contrib/CMakeLists.txt
@@ -5,13 +5,22 @@ add_subdirectory(zlib)
add_subdirectory(db)
add_subdirectory(ethereum)
-option(SECP256K1_BUILD_BENCHMARK "Build benchmarks." OFF)
-option(SECP256K1_BUILD_TESTS "Build tests." OFF)
-option(SECP256K1_BUILD_EXHAUSTIVE_TESTS "Build exhaustive tests." OFF)
-option(SECP256K1_BUILD_CTIME_TESTS "Build constant-time tests." OFF)
-option(SECP256K1_BUILD_EXAMPLES "Build examples." OFF)
-set_property(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1)
-add_subdirectory(bitcoin-secp256k1)
+if(USE_BITCOIN_SECP256K1_FOR_ECDSA)
+ option(SECP256K1_BUILD_BENCHMARK "Build benchmarks." OFF)
+ option(SECP256K1_BUILD_TESTS "Build tests." OFF)
+ option(SECP256K1_BUILD_EXHAUSTIVE_TESTS "Build exhaustive tests." OFF)
+ option(SECP256K1_BUILD_CTIME_TESTS "Build constant-time tests." OFF)
+ option(SECP256K1_BUILD_EXAMPLES "Build examples." OFF)
+ set_property(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1)
+
+ if(STATIC)
+ set(SECP256K1_DISABLE_SHARED ON CACHE BOOL "Disable shared library for secp256k1")
+ set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build static libraries by default" FORCE)
+ endif()
+ add_subdirectory(bitcoin-secp256k1)
+ set_property(TARGET secp256k1 PROPERTY FOLDER "contrib")
+ set_property(TARGET secp256k1_precomputed PROPERTY FOLDER "contrib")
+endif()
if( NOT DISABLE_TOR)
add_subdirectory(tor-connect)
@@ -31,8 +40,6 @@ set_property(TARGET libminiupnpc-static PROPERTY FOLDER "contrib")
set_property(TARGET zlibstatic PROPERTY FOLDER "contrib")
set_property(TARGET mdbx PROPERTY FOLDER "contrib")
set_property(TARGET lmdb PROPERTY FOLDER "contrib")
-set_property(TARGET secp256k1 PROPERTY FOLDER "contrib")
-set_property(TARGET secp256k1_precomputed PROPERTY FOLDER "contrib")
if( NOT DISABLE_TOR)
set_property(TARGET tor-connect PROPERTY FOLDER "contrib")
diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h
index 376af660..e32a9bc5 100644
--- a/contrib/epee/include/misc_log_ex.h
+++ b/contrib/epee/include/misc_log_ex.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019, Zano Project
+// Copyright (c) 2019-2024, Zano Project
// Copyright (c) 2019, anonimal
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
@@ -90,7 +90,7 @@ DISABLE_VS_WARNINGS(4100)
#define LOG_JOURNAL_MAX_ELEMENTS 100
#ifdef _DEBUG
- #define _ASSERTE__(expr) if(!expr) {__debugbreak();}
+ #define _ASSERTE__(expr) if(!(expr)) {__debugbreak();}
#else
#define _ASSERTE__(expr)
#endif
diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h
index b4466ad4..9e1ad044 100644
--- a/contrib/epee/include/net/http_server_handlers_map2.h
+++ b/contrib/epee/include/net/http_server_handlers_map2.h
@@ -282,8 +282,15 @@ namespace epee {
namespace http {
struct i_chain_handler
{
+ virtual bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response_info,
+ epee::net_utils::connection_context_base& conn_context, bool& call_found, documentation& docs = epee::net_utils::http::i_chain_handler::m_empty_documentation)
+ {
+ return this->handle_http_request_map(query_info, response_info, conn_context, call_found, docs);
+ }
+
virtual bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response_info,
epee::net_utils::connection_context_base& m_conn_context, bool& call_found, documentation& docs = epee::net_utils::http::i_chain_handler::m_empty_documentation) = 0;
+
static inline documentation m_empty_documentation;
};
@@ -365,7 +372,7 @@ namespace epee {
LOG_PRINT( "[HTTP/BIN][" << epee::string_tools::get_ip_string_from_int32(m_conn_context.m_remote_ip ) << "][" << query_info.m_URI << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \
}
-#define CHAIN_TO_PHANDLER(pi_chain_handler) else if (pi_chain_handler && pi_chain_handler->handle_http_request_map(query_info, response_info, m_conn_context, call_found, docs) && call_found) { return true;}
+#define CHAIN_TO_PHANDLER(pi_chain_handler) else if (pi_chain_handler && pi_chain_handler->handle_http_request(query_info, response_info, m_conn_context, call_found, docs) && call_found) { return true;}
#define CHAIN_URI_MAP2(callback) else {callback(query_info, response_info, m_conn_context);call_found = true;}
diff --git a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h
index d0d7c408..1bd2db1c 100644
--- a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h
+++ b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h
@@ -360,8 +360,12 @@ namespace epee
template< class t_type_stored, class t_type, class t_storage, typename cb_serialize>
static bool serialize_ephemeral(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname, cb_serialize cb_s)
{
- t_type_stored a = cb_s(d);
- return epee::serialization::selector::serialize(a, stg, hparent_section, pname);
+ t_type_stored a = AUTO_VAL_INIT(a);
+ bool add_val = cb_s(d, a);
+ if (add_val)
+ return epee::serialization::selector::serialize(a, stg, hparent_section, pname);
+ else
+ return true;
}
};
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 563b4266..4505b8f8 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -116,8 +116,13 @@ else()
endif()
add_library(crypto ${CRYPTO})
-add_dependencies(crypto secp256k1)
-target_link_libraries(crypto secp256k1)
+if(USE_BITCOIN_SECP256K1_FOR_ECDSA)
+ add_dependencies(crypto secp256k1)
+ target_link_libraries(crypto secp256k1)
+else()
+ add_dependencies(crypto OpenSSL::Crypto)
+ target_link_libraries(crypto OpenSSL::Crypto)
+endif()
add_library(currency_core ${CURRENCY_CORE})
add_dependencies(currency_core version ${PCH_LIB_NAME})
diff --git a/src/common/boost_serialization_maps.h b/src/common/boost_serialization_maps.h
index 5fbecea0..f6704b95 100644
--- a/src/common/boost_serialization_maps.h
+++ b/src/common/boost_serialization_maps.h
@@ -3,7 +3,10 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
-
+#include
+#ifndef DISABLE_PFR_SERIALIZATION_SELFCHECK
+ #include
+#endif
#define BEGIN_BOOST_SERIALIZATION() template void serialize(t_archive &_arch, const unsigned int ver) {
template struct TAssertEquality {
@@ -26,6 +29,60 @@ template struct TAssertEquality {
#define END_BOOST_SERIALIZATION() }
+
+/**********************************************************************************************************************************
+ This serialization closing macro adds self-validation by checking the total number of fields in the structure using boost::pfr.
+
+ Note: "num_fields" does NOT represent the number of fields included in the serialization. Instead, it indicates the total number
+ of fields in the structure, some of which might not be included in the serialization for valid reasons. If someone adds new
+ fields to the structure but forgets to update the serialization map, the compilation will fail. Any update to "num_fields" must
+ be accompanied by a thorough review of the serialization map to ensure no fields are omitted.
+**********************************************************************************************************************************/
+#ifndef DISABLE_PFR_SERIALIZATION_SELFCHECK
+ #define END_BOOST_SERIALIZATION_TOTAL_FIELDS(num_fields) static_assert(num_fields == boost::pfr::tuple_size::type>::value, "Unexpected number of fields!"); }
+#else
+ #define END_BOOST_SERIALIZATION_TOTAL_FIELDS(num_fields) END_BOOST_SERIALIZATION()
+#endif
+
+#define BOOST_SERIALIZATION_CURRENT_ARCHIVE_VER(current_version) static const unsigned int current_boost_version_serialization_version = current_version;
+
+#define LOOP_BACK_BOOST_SERIALIZATION_VERSION(type) BOOST_CLASS_VERSION(type, type::current_boost_version_serialization_version);
+
+
+
+template
+struct boost_transition_t {};
+
+template
+struct boost_transition_t
+{
+ template
+ static void chain_serialize(archive& ar, const origin_type& origin_tx)
+ {
+ destination_t dst_tx = AUTO_VAL_INIT(dst_tx);
+ transition_convert(origin_tx, dst_tx);
+ ar & dst_tx;
+ }
+};
+
+template
+struct boost_transition_t
+{
+ template
+ static void chain_serialize(archive& ar, origin_type& origin_tx)
+ {
+ // TODO: consider using move semantic for temporary 'dst_tx'
+ destination_t dst_tx = AUTO_VAL_INIT(dst_tx);
+ ar & dst_tx;
+ transition_convert(dst_tx, origin_tx);
+ }
+};
+
+
+#define BOOST_CHAIN_TRANSITION_VER(obj_version, old_type) if (obj_version == ver) {boost_transition_t::chain_serialize(_arch, *this);return;}
+
+#define BOOST_CHAIN_TRANSITION_IF_COND_TRUE(condition, old_type) if (condition) {boost_transition_t::chain_serialize(_arch, *this);return;}
+
/*
example of use:
diff --git a/src/common/crypto_serialization.h b/src/common/crypto_serialization.h
index 481b3ff2..21845ae9 100644
--- a/src/common/crypto_serialization.h
+++ b/src/common/crypto_serialization.h
@@ -313,5 +313,18 @@ namespace boost
{
a & reinterpret_cast(x);
}
+ template
+ inline void serialize(Archive& a, crypto::scalar_vec_t& x, const boost::serialization::version_type ver)
+ {
+ static_assert(sizeof(std::vector) == sizeof(crypto::scalar_vec_t));
+ a & static_cast&>(x);
+ }
+ template
+ inline void serialize(Archive& a, crypto::scalar_mat_t& x, const boost::serialization::version_type ver)
+ {
+ static_assert(sizeof(std::vector) == sizeof(crypto::scalar_mat_t));
+ a & static_cast&>(x);
+ }
+
} // namespace serialization
} // namespace boost
diff --git a/src/crypto/crypto-sugar.h b/src/crypto/crypto-sugar.h
index 9dad0b4e..3a76fa59 100644
--- a/src/crypto/crypto-sugar.h
+++ b/src/crypto/crypto-sugar.h
@@ -1083,7 +1083,6 @@ namespace crypto
make_random();
}
-
}; // scalar_vec_t
diff --git a/src/crypto/eth_signature.cpp b/src/crypto/eth_signature.cpp
index ba5b1358..c5e0999b 100644
--- a/src/crypto/eth_signature.cpp
+++ b/src/crypto/eth_signature.cpp
@@ -3,18 +3,245 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "eth_signature.h"
#include "crypto.h"
-#include "bitcoin-secp256k1/include/secp256k1.h"
+#ifndef USE_OPEN_SSL_FOR_ECDSA
+ #include "bitcoin-secp256k1/include/secp256k1.h"
+#endif
#include "random.h"
#include "misc_language.h"
#include
+#ifdef USE_OPEN_SSL_FOR_ECDSA
+ #include
+ #include
+ #include
+ #include
+ #include
+#endif
+
+
+// Function to create EC_KEY from raw 32 - byte private key
+EC_KEY * create_ec_key_from_private_key(const unsigned char* private_key) {
+ EC_KEY* key = EC_KEY_new_by_curve_name(NID_secp256k1);
+ if (!key) {
+ std::cerr << "Failed to create new EC Key" << std::endl;
+ return nullptr;
+ }
+
+ BIGNUM* priv_key_bn = BN_bin2bn(private_key, 32, nullptr);
+ if (!priv_key_bn) {
+ std::cerr << "Failed to convert private key to BIGNUM" << std::endl;
+ EC_KEY_free(key);
+ return nullptr;
+ }
+
+ if (!EC_KEY_set_private_key(key, priv_key_bn)) {
+ std::cerr << "Failed to set private key" << std::endl;
+ EC_KEY_free(key);
+ BN_free(priv_key_bn);
+ return nullptr;
+ }
+
+ BN_free(priv_key_bn);
+ return key;
+}
+
+
+void ensure_canonical_s(BIGNUM* s, const EC_GROUP* group) {
+ // Get the order of the curve
+ BIGNUM* order = BN_new();
+ EC_GROUP_get_order(group, order, nullptr);
+
+ // Compute half of the order: `n / 2`
+ BIGNUM* half_order = BN_new();
+ BN_rshift1(half_order, order);
+
+ // If `s` is greater than `n / 2`, replace `s` with `n - s`
+ if (BN_cmp(s, half_order) > 0) {
+ BN_sub(s, order, s);
+ }
+
+ BN_free(order);
+ BN_free(half_order);
+}
+
+// Update the function to ensure canonical `s`
+bool generate_ethereum_signature(const unsigned char* hash, const unsigned char* private_key, crypto::eth_signature& sig_res) {
+ EC_KEY* ec_key = create_ec_key_from_private_key(private_key);
+ if (!ec_key) {
+ throw std::runtime_error("Failed to create EC key from private key");
+ }
+
+ // Sign the hash
+ unsigned int sig_len = ECDSA_size(ec_key);
+ std::vector signature(sig_len);
+ if (ECDSA_sign(0, hash, 32, signature.data(), &sig_len, ec_key) == 0) {
+ EC_KEY_free(ec_key);
+ throw std::runtime_error("Failed to create signature");
+ }
+ signature.resize(sig_len);
+
+
+ // The OpenSSL ECDSA signature output is DER encoded, Ethereum expects (r, s, v)
+ const unsigned char* p = signature.data();
+ ECDSA_SIG* sig = d2i_ECDSA_SIG(nullptr, &p, sig_len);
+ if (!sig) {
+ EC_KEY_free(ec_key);
+ throw std::runtime_error("Failed to parse ECDSA signature");
+ }
+
+ const BIGNUM* r = nullptr;
+ const BIGNUM* s = nullptr;
+ ECDSA_SIG_get0(sig, &r, &s);
+
+ // Ensure canonical `s`
+ BIGNUM* s_canonical = BN_dup(s);
+ ensure_canonical_s(s_canonical, EC_KEY_get0_group(ec_key));
+
+ BN_bn2binpad(r, (unsigned char* )&sig_res.data[0], 32);
+ BN_bn2binpad(s_canonical, (unsigned char*)&sig_res.data[32], 32);
+
+
+ ECDSA_SIG_free(sig);
+ BN_free(s_canonical);
+ EC_KEY_free(ec_key);
+ return true;
+}
+
+// Convert raw 33-byte compressed public key to EC_KEY object
+EC_KEY* create_ec_key_from_compressed_public_key(const unsigned char* compressed_pub_key) {
+ EC_KEY* key = EC_KEY_new_by_curve_name(NID_secp256k1);
+ if (!key) {
+ std::cerr << "Failed to create EC_KEY object" << std::endl;
+ return nullptr;
+ }
+
+ EC_POINT* pub_point = EC_POINT_new(EC_KEY_get0_group(key));
+ if (!EC_POINT_oct2point(EC_KEY_get0_group(key), pub_point, compressed_pub_key, 33, nullptr)) {
+ std::cerr << "Failed to convert compressed public key" << std::endl;
+ EC_POINT_free(pub_point);
+ EC_KEY_free(key);
+ return nullptr;
+ }
+
+ if (!EC_KEY_set_public_key(key, pub_point)) {
+ std::cerr << "Failed to set public key" << std::endl;
+ EC_POINT_free(pub_point);
+ EC_KEY_free(key);
+ return nullptr;
+ }
+
+ EC_POINT_free(pub_point);
+ return key;
+}
+
+// Function to verify Ethereum-compatible signature
+bool verify_ethereum_signature(const crypto::hash& m, const crypto::eth_signature& sig_res, const crypto::eth_public_key& compressed_pub_key) {
+ EC_KEY* ec_key = create_ec_key_from_compressed_public_key((const unsigned char*)&compressed_pub_key.data[0]);
+ if (!ec_key) {
+ throw std::runtime_error("Failed to create EC key from compressed public key");
+ }
+ const unsigned char* r = (unsigned char*)&sig_res.data[0];
+ const unsigned char* s = (unsigned char*)&sig_res.data[32];
+ const unsigned char* hash = (unsigned char*)&m;
+
+ // Create ECDSA_SIG from r and s
+ BIGNUM* bn_r = BN_bin2bn(r, 32, nullptr);
+ BIGNUM* bn_s = BN_bin2bn(s, 32, nullptr);
+ if (!bn_r || !bn_s) {
+ EC_KEY_free(ec_key);
+ BN_free(bn_r);
+ BN_free(bn_s);
+ throw std::runtime_error("Failed to convert r or s to BIGNUM");
+ }
+
+ ECDSA_SIG* sig = ECDSA_SIG_new();
+ if (!sig) {
+ EC_KEY_free(ec_key);
+ BN_free(bn_r);
+ BN_free(bn_s);
+ throw std::runtime_error("Failed to create ECDSA_SIG object");
+ }
+
+ if (!ECDSA_SIG_set0(sig, bn_r, bn_s)) {
+ EC_KEY_free(ec_key);
+ ECDSA_SIG_free(sig);
+ BN_free(bn_r);
+ BN_free(bn_s);
+ throw std::runtime_error("Failed to set r and s in ECDSA_SIG");
+ }
+
+ // Verify the signature
+ int verification_result = ECDSA_do_verify(hash, 32, sig, ec_key);
+
+ ECDSA_SIG_free(sig);
+ EC_KEY_free(ec_key);
+
+
+ return verification_result == 1;
+}
+
+
+//
+// struct KeyPair {
+// std::vector private_key; // 32 bytes
+// std::vector public_key; // 33 bytes (compressed format)
+// };
+
+// Function to generate an Ethereum-compatible key pair
+bool generate_ethereum_key_pair(crypto::eth_secret_key& sec_key, crypto::eth_public_key& pub_key) {
+ /*KeyPair keypair;*/
+
+ // Create a new EC_KEY object with the secp256k1 curve
+ EC_KEY* key = EC_KEY_new_by_curve_name(NID_secp256k1);
+ if (!key) {
+ throw std::runtime_error("Failed to create new EC_KEY object");
+ }
+
+ // Generate the key pair
+ if (EC_KEY_generate_key(key) == 0) {
+ EC_KEY_free(key);
+ throw std::runtime_error("Failed to generate key pair");
+ }
+
+ // Extract the private key
+ const BIGNUM* priv_bn = EC_KEY_get0_private_key(key);
+ if (!priv_bn) {
+ EC_KEY_free(key);
+ throw std::runtime_error("Failed to get private key");
+ }
+
+ BN_bn2binpad(priv_bn, (unsigned char*)&sec_key.data[0], 32);
+
+ // Extract the public key in compressed format
+ const EC_POINT* pub_point = EC_KEY_get0_public_key(key);
+ if (!pub_point) {
+ EC_KEY_free(key);
+ throw std::runtime_error("Failed to get public key");
+ }
+
+ //keypair.public_key.resize(33); // Compressed format
+ if (EC_POINT_point2oct(EC_KEY_get0_group(key), pub_point, POINT_CONVERSION_COMPRESSED,
+ (unsigned char*)&pub_key.data[0], sizeof(pub_key.data), nullptr) == 0) {
+ EC_KEY_free(key);
+ throw std::runtime_error("Failed to convert public key to compressed format");
+ }
+
+ EC_KEY_free(key);
+ return true;
+}
+
+
+
+
+
namespace crypto
{
bool generate_eth_key_pair(eth_secret_key& sec_key, eth_public_key& pub_key) noexcept
{
try
{
+#ifndef USE_OPEN_SSL_FOR_ECDSA
secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
auto slh = epee::misc_utils::create_scope_leave_handler([&ctx](){
secp256k1_context_destroy(ctx);
@@ -44,6 +271,9 @@ namespace crypto
return false;
return true;
+#else
+ return generate_ethereum_key_pair(sec_key, pub_key);
+#endif
}
catch(...)
{
@@ -51,6 +281,7 @@ namespace crypto
}
}
+#ifndef USE_OPEN_SSL_FOR_ECDSA
bool eth_secret_key_to_public_key(const eth_secret_key& sec_key, eth_public_key& pub_key) noexcept
{
try
@@ -77,12 +308,13 @@ namespace crypto
return false;
}
}
-
+#endif
// generates secp256k1 ECDSA signature
bool generate_eth_signature(const hash& m, const eth_secret_key& sec_key, eth_signature& sig) noexcept
{
try
{
+#ifndef USE_OPEN_SSL_FOR_ECDSA
secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
auto slh = epee::misc_utils::create_scope_leave_handler([&ctx](){
secp256k1_context_destroy(ctx);
@@ -102,6 +334,9 @@ namespace crypto
return false;
return true;
+#else
+ return generate_ethereum_signature((const unsigned char*)&m.data, (unsigned char*)&sec_key.data, sig);
+#endif
}
catch(...)
{
@@ -115,7 +350,7 @@ namespace crypto
try
{
// TODO (performance) consider using secp256k1_context_static for verification -- sowle
-
+#ifndef USE_OPEN_SSL_FOR_ECDSA
secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
auto slh = epee::misc_utils::create_scope_leave_handler([&ctx](){
secp256k1_context_destroy(ctx);
@@ -141,6 +376,9 @@ namespace crypto
return false;
return true;
+#else
+ return verify_ethereum_signature(m, sig, pub_key);
+#endif
}
catch(...)
{
diff --git a/src/crypto/eth_signature.h b/src/crypto/eth_signature.h
index b12d41fe..4db0b8e7 100644
--- a/src/crypto/eth_signature.h
+++ b/src/crypto/eth_signature.h
@@ -31,7 +31,7 @@ namespace crypto
bool generate_eth_key_pair(eth_secret_key& sec_key, eth_public_key& pub_key) noexcept;
// converts eth_secret_key to eth_public_key
- bool eth_secret_key_to_public_key(const eth_secret_key& sec_key, eth_public_key& pub_key) noexcept;
+ //bool _eth_secret_key_to_public_key(const eth_secret_key& sec_key, eth_public_key& pub_key) noexcept;
// generates secp256k1 ECDSA signature
bool generate_eth_signature(const hash& m, const eth_secret_key& sec_key, eth_signature& sig) noexcept;
diff --git a/src/currency_core/account.cpp b/src/currency_core/account.cpp
index f5663826..ff194a59 100644
--- a/src/currency_core/account.cpp
+++ b/src/currency_core/account.cpp
@@ -86,6 +86,7 @@ namespace currency
std::vector processed_seed_binary = keys_seed_binary;
if (!password.empty())
{
+ CHECK_AND_ASSERT_THROW_MES(currency::validate_password(password), "seed phrase password contains invalid characters, seed phrase cannot be created with such a password");
//encrypt seed phrase binary data
crypt_with_pass(&keys_seed_binary[0], keys_seed_binary.size(), &processed_seed_binary[0], password);
}
@@ -107,6 +108,9 @@ namespace currency
uint64_t h_64 = *reinterpret_cast(&h);
uint16_t checksum = h_64 % (checksum_max + 1);
+ if (checksum == checksum_max) // workaround for incorrect checksum calculation (trying to keep the whole scheme untouched) -- sowle
+ checksum = 0;
+
uint8_t auditable_flag = 0;
if (m_keys.account_address.flags & ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE)
auditable_flag = 1;
@@ -215,6 +219,10 @@ namespace currency
h = crypto::cn_fast_hash(&h, sizeof h);
uint64_t h_64 = *reinterpret_cast(&h);
uint16_t checksum_calculated = h_64 % (checksum_max + 1);
+
+ if (checksum_calculated == checksum_max) // workaround for incorrect checksum calculation (trying to keep the whole scheme untouched) -- sowle
+ checksum_calculated = 0;
+
if (checksum != checksum_calculated)
{
LOG_PRINT_L0("seed phase has invalid checksum: " << checksum_calculated << ", while " << checksum << " is expected, check your words");
@@ -229,6 +237,8 @@ namespace currency
if (auditable_flag)
m_keys.account_address.flags |= ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE;
+ else
+ m_keys.account_address.flags &= ~ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE;
return true;
}
diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp
index 6d4cbc1f..0d6d41f8 100644
--- a/src/currency_core/blockchain_storage.cpp
+++ b/src/currency_core/blockchain_storage.cpp
@@ -830,7 +830,7 @@ bool blockchain_storage::purge_transaction_from_blockchain(const crypto::hash& t
fee = get_tx_fee(tx_res_ptr->tx);
purge_transaction_keyimages_from_blockchain(tx, true);
- bool r = unprocess_blockchain_tx_extra(tx);
+ bool r = unprocess_blockchain_tx_extra(tx, tx_res_ptr->m_keeper_block_height);
CHECK_AND_ASSERT_MES(r, false, "failed to unprocess_blockchain_tx_extra for tx " << tx_id);
r = unprocess_blockchain_tx_attachments(tx, get_current_blockchain_size(), 0/*TODO: add valid timestamp here in future if need*/);
@@ -1553,8 +1553,20 @@ bool blockchain_storage::create_block_template(const create_block_template_param
}
diffic = get_next_diff_conditional(pos);
+ CHECK_AND_ASSERT_MES(diffic, false, "get_next_diff_conditional failed");
+
+ // check PoW block timestamp against the current blockchain timestamp median -- if it's not okay, don't create a new block
+ // TODO (performance) both get_next_diff_conditional and get_last_n_blocks_timestamps obtains last N blocks, consider data reusing -- sowle
+ if (!pos && !params.ignore_pow_ts_check)
+ {
+ uint64_t median_ts = get_last_n_blocks_timestamps_median(BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW);
+ if(b.timestamp < median_ts)
+ {
+ LOG_PRINT_YELLOW("Block template construction failed because current core timestamp, " << b.timestamp << ", is less than median of last " << BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW << " blocks, " << median_ts, LOG_LEVEL_2);
+ return false;
+ }
+ }
- CHECK_AND_ASSERT_MES(diffic, false, "difficulty owverhead.");
@@ -3805,7 +3817,7 @@ bool blockchain_storage::pop_transaction_from_global_index(const transaction& tx
return true;
}
//------------------------------------------------------------------
-bool blockchain_storage::unprocess_blockchain_tx_extra(const transaction& tx)
+bool blockchain_storage::unprocess_blockchain_tx_extra(const transaction& tx, const uint64_t height)
{
tx_extra_info ei = AUTO_VAL_INIT(ei);
bool r = parse_and_validate_tx_extra(tx, ei);
@@ -3818,9 +3830,7 @@ bool blockchain_storage::unprocess_blockchain_tx_extra(const transaction& tx)
if (ei.m_asset_operation.operation_type != ASSET_DESCRIPTOR_OPERATION_UNDEFINED)
{
- crypto::public_key asset_id = currency::null_pkey;
- CHECK_AND_ASSERT_MES(get_or_calculate_asset_id(ei.m_asset_operation, nullptr, &asset_id), false, "get_or_calculate_asset_id failed");
- r = pop_asset_info(asset_id);
+ r = pop_asset_info(ei.m_asset_operation, height);
CHECK_AND_ASSERT_MES(r, false, "failed to pop_alias_info");
}
return true;
@@ -3862,15 +3872,16 @@ bool blockchain_storage::get_asset_info(const crypto::public_key& asset_id, asse
{
CRITICAL_REGION_LOCAL(m_read_lock);
auto as_ptr = m_db_assets.find(asset_id);
- if (as_ptr)
- {
- if (as_ptr->size())
- {
- result = as_ptr->back().descriptor;
- return true;
- }
- }
- return false;
+ if (!as_ptr)
+ return false;
+ if (as_ptr->empty())
+ return false;
+ // the last history item must have opt_descriptor, but we check it just to be sure
+ if (!as_ptr->back().opt_descriptor.has_value())
+ return false;
+
+ result = as_ptr->back().opt_descriptor.get();
+ return true;
}
//------------------------------------------------------------------
uint64_t blockchain_storage::get_assets(uint64_t offset, uint64_t count, std::list& assets) const
@@ -3882,15 +3893,19 @@ uint64_t blockchain_storage::get_assets(uint64_t offset, uint64_t count, std::li
if (i < offset)
return true; // continue
- CHECK_AND_ASSERT_THROW_MES(asset_descriptor_history.size(), "asset_descriptor_history unexpectedly have 0 size, asset_id: " << asset_id);
- assets.push_back(asset_descriptor_with_id());
- static_cast(assets.back()) = asset_descriptor_history.back().descriptor;
- assets.back().asset_id = asset_id;
+ CHECK_AND_ASSERT_THROW_MES(asset_descriptor_history.size(), "unexpectedly, the asset_descriptor_history is empty; asset_id: " << asset_id);
+ CHECK_AND_ASSERT_THROW_MES(asset_descriptor_history.back().opt_descriptor.has_value(), "the last element of asset_descriptor_history doesn't have descriptor; asset_id: " << asset_id);
+ asset_descriptor_with_id& added_item = assets.emplace_back();
+ asset_descriptor_base& added_item_adb = static_cast(added_item);
+ added_item_adb = asset_descriptor_history.back().opt_descriptor.get();
+ replace_asset_ticker_and_full_name_if_invalid(added_item_adb, asset_id);
+ added_item.asset_id = asset_id;
+
if (assets.size() >= count)
{
- return false;
+ return false; // stop
}
- return true;
+ return true; // continue
});
return assets.size();
}
@@ -4084,21 +4099,79 @@ bool blockchain_storage::put_alias_info(const transaction & tx, extra_alias_entr
return true;
}
//------------------------------------------------------------------
-bool blockchain_storage::pop_asset_info(const crypto::public_key& asset_id)
+bool blockchain_storage::pop_asset_info(const asset_descriptor_operation& ado, const uint64_t height)
{
CRITICAL_REGION_LOCAL(m_read_lock);
+ crypto::public_key asset_id = currency::null_pkey;
+ CHECK_AND_ASSERT_MES(get_or_calculate_asset_id(ado, nullptr, &asset_id), false, "get_or_calculate_asset_id failed");
+
auto asset_history_ptr = m_db_assets.find(asset_id);
CHECK_AND_ASSERT_MES(asset_history_ptr && asset_history_ptr->size(), false, "empty name list in pop_asset_info");
-
+
assets_container::t_value_type local_asset_hist = *asset_history_ptr;
- local_asset_hist.pop_back();
+
+ if (is_hardfork_active_for_height(ZANO_HARDFORK_05, height))
+ {
+ // NEW HF5 handling
+ assets_container::t_value_type local_asset_hist = *asset_history_ptr;
+ asset_descriptor_operation& last_ado = local_asset_hist.back(); // above we made sure that the history isn't empty
+ CHECK_AND_ASSERT_MES(last_ado.opt_descriptor.has_value(), false, "opt_descriptor is missing during asset pop, op: " << (int)ado.operation_type);
+ asset_descriptor_base& last_adb = last_ado.opt_descriptor.get();
+
+ if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT)
+ {
+ // just change the most recent history record, don't pop
+ if (last_adb.hidden_supply)
+ {
+ //CHECK_AND_ASSERT_MES(last_ado.opt_amount_commitment.has_value() && ado.opt_amount_commitment.has_value(), false, "last_ado.opt_amount_commitment or ado.opt_amount_commitment is missing (emit)");
+ //last_ado.opt_amount_commitment.get() = (crypto::point_t(last_ado.opt_amount_commitment.get()) - crypto::point_t(ado.opt_amount_commitment.get())).to_public_key();
+ return false; // not supported atm
+ }
+ else
+ {
+ CHECK_AND_ASSERT_MES(ado.opt_amount.has_value(), false, "last_ado.opt_amount or ado.opt_amount is missing (emit)");
+ last_adb.current_supply -= ado.opt_amount.get();
+ }
+ }
+ else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
+ {
+ // just change the most recent history record, don't pop
+ if (last_adb.hidden_supply)
+ {
+ //CHECK_AND_ASSERT_MES(last_ado.opt_amount_commitment.has_value() && ado.opt_amount_commitment.has_value(), false, "last_ado.opt_amount_commitment or ado.opt_amount_commitment is missing (burn)");
+ //last_ado.opt_amount_commitment.get() = (crypto::point_t(last_ado.opt_amount_commitment.get()) + crypto::point_t(ado.opt_amount_commitment.get())).to_public_key();
+ return false; // not supported atm
+ }
+ else
+ {
+ CHECK_AND_ASSERT_MES(ado.opt_amount.has_value(), false, "last_ado.opt_amount or ado.opt_amount is missing (burn)");
+ last_adb.current_supply += ado.opt_amount.get();
+ }
+ }
+ else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE)
+ {
+ // just pop the most recent history record
+ local_asset_hist.pop_back();
+ }
+ else
+ {
+ CHECK_AND_ASSERT_MES(false, false, "invalid operation: " << (int)ado.operation_type);
+ }
+ }
+ else
+ {
+ // HF4
+ local_asset_hist.pop_back();
+ }
+
+ // both HF4 and HF5
if (local_asset_hist.size())
m_db_assets.set(asset_id, local_asset_hist);
else
m_db_assets.erase(asset_id);
-
LOG_PRINT_MAGENTA("[ASSET_POP]: " << asset_id << ": " << (!local_asset_hist.empty() ? "(prev)" : "(erased)"), LOG_LEVEL_1);
+
return true;
}
//------------------------------------------------------------------
@@ -4107,16 +4180,18 @@ bool blockchain_storage::validate_ado_ownership(asset_op_verification_context& a
bool r = false;
CHECK_AND_ASSERT_MES(avc.asset_op_history->size() != 0, false, "asset with id " << avc.asset_id << " has empty history record");
const asset_descriptor_operation& last_ado = avc.asset_op_history->back();
+ CHECK_AND_ASSERT_MES(last_ado.opt_descriptor.has_value(), false, "last ado is missing opt_descriptor; asset id: " << avc.asset_id);
+ const asset_descriptor_base& last_adb = last_ado.opt_descriptor.get();
- if (is_hardfork_active(ZANO_HARDFORK_05)) // TODO: consider changing to height-specific check
+ if (is_hardfork_active_for_height(ZANO_HARDFORK_05, avc.height))
{
- if (last_ado.descriptor.owner_eth_pub_key.has_value())
+ if (last_adb.owner_eth_pub_key.has_value())
{
- CHECK_AND_ASSERT_MES(last_ado.descriptor.owner == null_pkey, false, "owner_eth_pub_key is set but owner pubkey is nonzero");
+ CHECK_AND_ASSERT_MES(last_adb.owner == null_pkey, false, "owner_eth_pub_key is set but owner pubkey is nonzero");
asset_operation_ownership_proof_eth aoop_eth{};
r = get_type_in_variant_container(avc.tx.proofs, aoop_eth);
CHECK_AND_ASSERT_MES(r, false, "Ownership validation failed: asset_operation_ownership_proof_eth is missing");
- if (!crypto::verify_eth_signature(avc.tx_id, last_ado.descriptor.owner_eth_pub_key.value(), aoop_eth.eth_sig))
+ if (!crypto::verify_eth_signature(avc.tx_id, last_adb.owner_eth_pub_key.value(), aoop_eth.eth_sig))
{
LOG_ERROR("Failed to validate secp256k1 signature for hash: " << avc.tx_id << ", signature: " << aoop_eth.eth_sig);
return false;
@@ -4133,12 +4208,13 @@ bool blockchain_storage::validate_ado_ownership(asset_op_verification_context& a
r = get_type_in_variant_container(avc.tx.proofs, aoop);
CHECK_AND_ASSERT_MES(r, false, "Ownership validation failed: asset_operation_ownership_proof is missing");
- return crypto::verify_schnorr_sig(avc.tx_id, last_ado.descriptor.owner, aoop.gss);
+ return crypto::verify_schnorr_sig(avc.tx_id, last_adb.owner, aoop.gss);
}
//------------------------------------------------------------------
-bool blockchain_storage::validate_asset_operation_against_current_blochain_state(asset_op_verification_context& avc) const
+bool blockchain_storage::validate_asset_operation_hf4(asset_op_verification_context& avc) const
{
CRITICAL_REGION_LOCAL(m_read_lock);
+ CHECK_AND_ASSERT_MES(!is_hardfork_active_for_height(ZANO_HARDFORK_05, avc.height), false, "validate_asset_operation_hf4 was called in HF5");
CHECK_AND_ASSERT_MES(get_or_calculate_asset_id(avc.ado, &avc.asset_id_pt, &avc.asset_id), false, "get_or_calculate_asset_id failed");
avc.asset_op_history = m_db_assets.find(avc.asset_id);
@@ -4150,16 +4226,25 @@ bool blockchain_storage::validate_asset_operation_against_current_blochain_state
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
{
CHECK_AND_ASSERT_MES(!avc.asset_op_history, false, "asset with id " << avc.asset_id << " has already been registered");
- avc.amount_to_validate = ado.descriptor.current_supply;
- if(this->is_hardfork_active(ZANO_HARDFORK_05))
- {
- CHECK_AND_ASSERT_MES(validate_ado_initial(ado.descriptor), false, "validate_ado_initial failed!");
- }
+ CHECK_AND_ASSERT_MES(ado.opt_descriptor.has_value(), false, "opt_descriptor is missing while registering asset " << avc.asset_id);
+
+ // CZ please review the following two added lines, do we need them _here_? I think they should go to hardfork_specific_terms...
+ // anyway, we musn't miss these checks for the sake of consensus
+ CHECK_AND_ASSERT_MES(!ado.opt_descriptor.get().owner_eth_pub_key.has_value(), false, "owner_eth_pub_key is prohibited before HF5");
+ CHECK_AND_ASSERT_MES(!ado.opt_asset_id_salt.has_value(), false, "opt_asset_id_salt is prohibited before HF5");
+
+ CHECK_AND_ASSERT_MES(ado.opt_descriptor.has_value(), false, "opt_descriptor is missing while registering asset " << avc.asset_id);
+ avc.amount_to_validate = ado.opt_descriptor.get().current_supply;
}
else
{
CHECK_AND_ASSERT_MES(avc.asset_op_history && avc.asset_op_history->size() > 0, false, "asset with id " << avc.asset_id << " has not been registered");
const asset_descriptor_operation& last_ado = avc.asset_op_history->back();
+ CHECK_AND_ASSERT_MES(last_ado.opt_descriptor.has_value(), false, "opt_descriptor is missing in last ado, op: " << (int)ado.operation_type);
+ const asset_descriptor_base& last_adb = last_ado.opt_descriptor.get();
+ CHECK_AND_ASSERT_MES(ado.opt_descriptor.has_value(), false, "opt_descriptor is missing in ado, op: " << (int)ado.operation_type);
+ const asset_descriptor_base adb = ado.opt_descriptor.get();
+
// check ownership permission
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE)
{
@@ -4171,23 +4256,23 @@ bool blockchain_storage::validate_asset_operation_against_current_blochain_state
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE)
{
//check that total current_supply haven't changed
- CHECK_AND_ASSERT_MES(ado.descriptor.current_supply == last_ado.descriptor.current_supply, false, "update operation attempted to change emission, failed");
- CHECK_AND_ASSERT_MES(validate_ado_update_allowed(ado.descriptor, last_ado.descriptor), false, "update operation modifies asset descriptor in a prohibited manner");
+ CHECK_AND_ASSERT_MES(adb.current_supply == last_adb.current_supply, false, "update operation attempted to change emission, failed");
+ CHECK_AND_ASSERT_MES(validate_ado_update_allowed(adb, last_adb), false, "update operation modifies asset descriptor in a prohibited manner");
need_to_validate_ao_amount_commitment = false;
}
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT)
{
- CHECK_AND_ASSERT_MES(ado.descriptor.current_supply > last_ado.descriptor.current_supply, false, "emit operation does not increase the current supply, failed");
- CHECK_AND_ASSERT_MES(validate_ado_update_allowed(ado.descriptor, last_ado.descriptor), false, "emit operation modifies asset descriptor in a prohibited manner");
- CHECK_AND_ASSERT_MES(ado.descriptor.meta_info == last_ado.descriptor.meta_info, false, "emit operation is not allowed to update meta info");
- avc.amount_to_validate = ado.descriptor.current_supply - last_ado.descriptor.current_supply;
+ CHECK_AND_ASSERT_MES(adb.current_supply > last_adb.current_supply, false, "emit operation does not increase the current supply, failed");
+ CHECK_AND_ASSERT_MES(validate_ado_update_allowed(adb, last_adb), false, "emit operation modifies asset descriptor in a prohibited manner");
+ CHECK_AND_ASSERT_MES(adb.meta_info == last_adb.meta_info, false, "emit operation is not allowed to update meta info");
+ avc.amount_to_validate = adb.current_supply - last_adb.current_supply;
}
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
{
- CHECK_AND_ASSERT_MES(ado.descriptor.current_supply < last_ado.descriptor.current_supply, false, "burn operation does not decrease the current supply, failed");
- CHECK_AND_ASSERT_MES(validate_ado_update_allowed(ado.descriptor, last_ado.descriptor), false, "burn operation modifies asset descriptor in a prohibited manner");
- CHECK_AND_ASSERT_MES(ado.descriptor.meta_info == last_ado.descriptor.meta_info, false, "burn operation is not allowed to update meta info");
- avc.amount_to_validate = last_ado.descriptor.current_supply - ado.descriptor.current_supply;
+ CHECK_AND_ASSERT_MES(adb.current_supply < last_adb.current_supply, false, "burn operation does not decrease the current supply, failed");
+ CHECK_AND_ASSERT_MES(validate_ado_update_allowed(adb, last_adb), false, "burn operation modifies asset descriptor in a prohibited manner");
+ CHECK_AND_ASSERT_MES(adb.meta_info == last_adb.meta_info, false, "burn operation is not allowed to update meta info");
+ avc.amount_to_validate = last_adb.current_supply - adb.current_supply;
}
else
{
@@ -4205,35 +4290,208 @@ bool blockchain_storage::validate_asset_operation_against_current_blochain_state
return true;
}
//------------------------------------------------------------------
-bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado)
+bool blockchain_storage::validate_asset_operation_hf5(asset_op_verification_context& avc) const
+{
+ CRITICAL_REGION_LOCAL(m_read_lock);
+ CHECK_AND_ASSERT_MES(is_hardfork_active_for_height(ZANO_HARDFORK_05, avc.height), false, "validate_asset_operation was called before HF5");
+
+ CHECK_AND_ASSERT_MES(get_or_calculate_asset_id(avc.ado, &avc.asset_id_pt, &avc.asset_id), false, "get_or_calculate_asset_id failed");
+ avc.asset_op_history = m_db_assets.find(avc.asset_id);
+
+ const asset_descriptor_operation& ado = avc.ado;
+
+ bool need_to_validate_ao_amount_commitment = true;
+
+ if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
+ {
+ CHECK_AND_ASSERT_MES(!avc.asset_op_history, false, "asset with id " << avc.asset_id << " has already been registered");
+ CHECK_AND_ASSERT_MES(ado.opt_descriptor.has_value(), false, "opt_descriptor is missing while registering asset " << avc.asset_id);
+ avc.amount_to_validate = ado.opt_descriptor.get().current_supply;
+ // HF5 specific
+ CHECK_AND_ASSERT_MES(validate_ado_initial(ado.opt_descriptor.get()), false, "validate_ado_initial failed!");
+ CHECK_AND_ASSERT_MES(ado.opt_amount.has_value() && avc.amount_to_validate == ado.opt_amount.get(), false, "opt_amount is missing or incorrect");
+ }
+ else
+ {
+ CHECK_AND_ASSERT_MES(avc.asset_op_history && avc.asset_op_history->size() > 0, false, "asset with id " << avc.asset_id << " has not been registered");
+ const asset_descriptor_operation& last_ado = avc.asset_op_history->back();
+ CHECK_AND_ASSERT_MES(last_ado.opt_descriptor.has_value(), false, "opt_descriptor is missing in last ado, op: " << (int)ado.operation_type);
+ const asset_descriptor_base& last_adb = last_ado.opt_descriptor.get();
+
+ // check ownership permission
+ if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE)
+ {
+ bool r = validate_ado_ownership(avc);
+ CHECK_AND_ASSERT_MES(r, false, "Failed to validate ownership of asset_descriptor_operation, rejecting");
+ }
+
+ avc.amount_to_validate = 0;
+ if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE)
+ {
+ CHECK_AND_ASSERT_MES(ado.opt_descriptor.has_value(), false, "opt_descriptor is missing (update)");
+ //check that total current_supply haven't changed
+ CHECK_AND_ASSERT_MES(ado.opt_descriptor.get().current_supply == last_adb.current_supply, false, "update operation attempted to change emission, failed");
+ CHECK_AND_ASSERT_MES(validate_ado_update_allowed(ado.opt_descriptor.get(), last_adb), false, "update operation modifies asset descriptor in a prohibited manner");
+ need_to_validate_ao_amount_commitment = false;
+ }
+ else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT)
+ {
+ //CHECK_AND_ASSERT_MES(ado.descriptor.current_supply > last_adb.current_supply, false, "emit operation does not increase the current supply, failed");
+ //CHECK_AND_ASSERT_MES(validate_ado_update_allowed(ado.descriptor, last_adb), false, "emit operation modifies asset descriptor in a prohibited manner");
+ //CHECK_AND_ASSERT_MES(ado.descriptor.meta_info == last_adb.meta_info, false, "emit operation is not allowed to update meta info");
+
+ if (!last_adb.hidden_supply)
+ {
+ CHECK_AND_ASSERT_MES(ado.opt_amount.has_value(), false, "opt_amount is missing (emit)");
+ uint64_t amount = ado.opt_amount.get();
+
+ CHECK_AND_ASSERT_MES(last_adb.current_supply + amount >= last_adb.current_supply, false, "current_supply overflow: " << last_adb.current_supply << ", amount: " << amount << " (emit)");
+ CHECK_AND_ASSERT_MES(last_adb.current_supply + amount <= last_adb.total_max_supply, false, "current_supply overflow: " << last_adb.current_supply << ", amount: " << amount << ", max supply: " << last_adb.total_max_supply << " (emit)");
+ avc.amount_to_validate = amount;
+ }
+ }
+ else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
+ {
+ //CHECK_AND_ASSERT_MES(ado.descriptor.current_supply < last_adb.current_supply, false, "burn operation does not decrease the current supply, failed");
+ //CHECK_AND_ASSERT_MES(validate_ado_update_allowed(ado.descriptor, last_adb), false, "burn operation modifies asset descriptor in a prohibited manner");
+ //CHECK_AND_ASSERT_MES(ado.descriptor.meta_info == last_adb.meta_info, false, "burn operation is not allowed to update meta info");
+
+ if (!last_adb.hidden_supply)
+ {
+ CHECK_AND_ASSERT_MES(ado.opt_amount.has_value(), false, "opt_amount is missing (burn)");
+ uint64_t amount = ado.opt_amount.get();
+
+ CHECK_AND_ASSERT_MES(last_adb.current_supply - amount <= last_adb.current_supply, false, "current_supply overflow: " << last_adb.current_supply << ", amount: " << amount << " (burn)");
+ avc.amount_to_validate = amount;
+ }
+ }
+ else
+ {
+ LOG_ERROR("Unknown operation type: " << (int)ado.operation_type);
+ return false;
+ }
+ }
+
+ if (need_to_validate_ao_amount_commitment)
+ {
+ bool r = validate_asset_operation_amount_commitment(avc);
+ CHECK_AND_ASSERT_MES(r, false, "Balance proof validation failed for asset_descriptor_operation");
+ }
+
+ return true;
+}
+//------------------------------------------------------------------
+bool blockchain_storage::validate_asset_operation(asset_op_verification_context& avc, uint64_t height) const
+{
+ if (is_hardfork_active_for_height(ZANO_HARDFORK_05, height))
+ {
+ return validate_asset_operation_hf5(avc);
+ }
+ else
+ {
+ return validate_asset_operation_hf4(avc);
+ }
+}
+//------------------------------------------------------------------
+bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado, const uint64_t height)
{
CRITICAL_REGION_LOCAL(m_read_lock);
- asset_op_verification_context avc = { tx, tx_id, ado };
- CHECK_AND_ASSERT_MES(validate_asset_operation_against_current_blochain_state(avc), false, "asset operation validation failed");
+ asset_op_verification_context avc = { tx, tx_id, ado, height };
+ CHECK_AND_ASSERT_MES(validate_asset_operation(avc, height), false, "asset operation validation failed");
- assets_container::t_value_type local_asset_history{};
- if (avc.asset_op_history)
- local_asset_history = *avc.asset_op_history;
- local_asset_history.push_back(ado);
- m_db_assets.set(avc.asset_id, local_asset_history);
-
- switch(ado.operation_type)
+ if (is_hardfork_active_for_height(ZANO_HARDFORK_05, height))
{
- case ASSET_DESCRIPTOR_OPERATION_REGISTER:
- LOG_PRINT_MAGENTA("[ASSET_REGISTERED]: " << print_money_brief(ado.descriptor.current_supply, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1);
- break;
- case ASSET_DESCRIPTOR_OPERATION_UPDATE:
- LOG_PRINT_MAGENTA("[ASSET_UPDATED]: " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1);
- break;
- case ASSET_DESCRIPTOR_OPERATION_EMIT:
- LOG_PRINT_MAGENTA("[ASSET_EMITTED]: " << print_money_brief(avc.amount_to_validate, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1);
- break;
- case ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN:
- LOG_PRINT_MAGENTA("[ASSET_BURNT]: " << print_money_brief(avc.amount_to_validate, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1);
- break;
- default:
- LOG_ERROR("Unknown operation type: " << (int)ado.operation_type);
+ // NEW HF5 handling here
+
+ assets_container::t_value_type local_asset_history{};
+ if (avc.asset_op_history)
+ local_asset_history = *avc.asset_op_history;
+
+ if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
+ {
+ CHECK_AND_ASSERT_MES(ado.opt_descriptor.has_value(), false, "opt_descriptor is missing (register)"); // validated in validate_asset_operation(), just in case
+ const asset_descriptor_base& adb = ado.opt_descriptor.get();
+ local_asset_history.push_back(ado);
+ LOG_PRINT_MAGENTA("[ASSET_REGISTERED]: " << print_money_brief(adb.current_supply, adb.decimal_point) << ", " << avc.asset_id << ": " << adb.ticker << ", \"" << adb.full_name << "\"", LOG_LEVEL_1);
+ }
+ else
+ {
+ CHECK_AND_ASSERT_MES(!local_asset_history.empty(), false, "local_asset_history is empty (update/emit/burn)");
+ asset_descriptor_operation& last_ado = local_asset_history.back();
+ CHECK_AND_ASSERT_MES(last_ado.opt_descriptor.has_value(), false, "last_ado.opt_descriptor is missing (update/emit/burn)");
+ asset_descriptor_base& last_adb = local_asset_history.back().opt_descriptor.get();
+
+ if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE)
+ {
+ local_asset_history.push_back(ado);
+ LOG_PRINT_MAGENTA("[ASSET_UPDATED]: " << avc.asset_id << ": " << last_adb.ticker << ", \"" << last_adb.full_name << "\"", LOG_LEVEL_1);
+ }
+ else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT)
+ {
+ // just change the most recent history record, don't push
+ if (last_adb.hidden_supply)
+ {
+ //CHECK_AND_ASSERT_MES(last_ado.opt_amount_commitment.has_value() && ado.opt_amount_commitment.has_value(), false, "last_ado.opt_amount_commitment or ado.opt_amount_commitment is missing (emit)");
+ //last_ado.opt_amount_commitment.get() = (crypto::point_t(last_ado.opt_amount_commitment.get()) + crypto::point_t(ado.opt_amount_commitment.get())).to_public_key();
+ return false; // not supported atm
+ }
+ else
+ {
+ CHECK_AND_ASSERT_MES(ado.opt_amount.has_value(), false, "last_ado.opt_amount or ado.opt_amount is missing (emit)");
+ last_adb.current_supply += ado.opt_amount.get();
+ }
+ LOG_PRINT_MAGENTA("[ASSET_EMITTED]: " << print_money_brief(avc.amount_to_validate, last_adb.decimal_point) << ", " << avc.asset_id << ": " << last_adb.ticker << ", \"" << last_adb.full_name << "\"", LOG_LEVEL_1);
+ }
+ else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
+ {
+ // just change the most recent history record, don't push
+ if (last_adb.hidden_supply)
+ {
+ //CHECK_AND_ASSERT_MES(last_ado.opt_amount_commitment.has_value() && ado.opt_amount_commitment.has_value(), false, "last_ado.opt_amount_commitment or ado.opt_amount_commitment is missing (burn)");
+ //last_ado.opt_amount_commitment.get() = (crypto::point_t(last_ado.opt_amount_commitment.get()) - crypto::point_t(ado.opt_amount_commitment.get())).to_public_key();
+ return false; // not supported atm
+ }
+ else
+ {
+ CHECK_AND_ASSERT_MES(ado.opt_amount.has_value(), false, "last_ado.opt_amount or ado.opt_amount is missing (burn)");
+ last_adb.current_supply -= ado.opt_amount.get();
+ }
+ LOG_PRINT_MAGENTA("[ASSET_BURNT]: " << print_money_brief(avc.amount_to_validate, last_adb.decimal_point) << ", " << avc.asset_id << ": " << last_adb.ticker << ", \"" << last_adb.full_name << "\"", LOG_LEVEL_1);
+ }
+ else
+ CHECK_AND_ASSERT_MES(false, false, "Unknown operation type: " << (int)ado.operation_type);
+ }
+
+ m_db_assets.set(avc.asset_id, local_asset_history);
+ }
+ else
+ {
+ // HF4
+ assets_container::t_value_type local_asset_history{};
+ if (avc.asset_op_history)
+ local_asset_history = *avc.asset_op_history;
+ local_asset_history.push_back(ado);
+ m_db_assets.set(avc.asset_id, local_asset_history);
+
+ const asset_descriptor_base& adb = ado.opt_descriptor.get(); // in HF4 descriptor must always be present, validated in validate_asset_operation_hf4()
+ switch(ado.operation_type)
+ {
+ case ASSET_DESCRIPTOR_OPERATION_REGISTER:
+ LOG_PRINT_MAGENTA("[ASSET_REGISTERED]: " << print_money_brief(adb.current_supply, adb.decimal_point) << ", " << avc.asset_id << ": " << adb.ticker << ", \"" << adb.full_name << "\"", LOG_LEVEL_1);
+ break;
+ case ASSET_DESCRIPTOR_OPERATION_UPDATE:
+ LOG_PRINT_MAGENTA("[ASSET_UPDATED]: " << avc.asset_id << ": " << adb.ticker << ", \"" << adb.full_name << "\"", LOG_LEVEL_1);
+ break;
+ case ASSET_DESCRIPTOR_OPERATION_EMIT:
+ LOG_PRINT_MAGENTA("[ASSET_EMITTED]: " << print_money_brief(avc.amount_to_validate, adb.decimal_point) << ", " << avc.asset_id << ": " << adb.ticker << ", \"" << adb.full_name << "\"", LOG_LEVEL_1);
+ break;
+ case ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN:
+ LOG_PRINT_MAGENTA("[ASSET_BURNT]: " << print_money_brief(avc.amount_to_validate, adb.decimal_point) << ", " << avc.asset_id << ": " << adb.ticker << ", \"" << adb.full_name << "\"", LOG_LEVEL_1);
+ break;
+ default:
+ LOG_ERROR("Unknown operation type: " << (int)ado.operation_type);
+ }
}
return true;
@@ -4309,7 +4567,7 @@ bool blockchain_storage::prevalidate_alias_info(const transaction& tx, const ext
return true;
}
//------------------------------------------------------------------
-bool blockchain_storage::process_blockchain_tx_extra(const transaction& tx, const crypto::hash& tx_id)
+bool blockchain_storage::process_blockchain_tx_extra(const transaction& tx, const crypto::hash& tx_id, const uint64_t height)
{
//check transaction extra
tx_extra_info ei = AUTO_VAL_INIT(ei);
@@ -4325,7 +4583,7 @@ bool blockchain_storage::process_blockchain_tx_extra(const transaction& tx, cons
}
if (ei.m_asset_operation.operation_type != ASSET_DESCRIPTOR_OPERATION_UNDEFINED)
{
- r = put_asset_info(tx, tx_id, ei.m_asset_operation);
+ r = put_asset_info(tx, tx_id, ei.m_asset_operation, height);
CHECK_AND_ASSERT_MES(r, false, "failed to put_asset_info");
}
@@ -4525,7 +4783,7 @@ bool blockchain_storage::add_transaction_from_block(const transaction& tx, const
CHECK_AND_ASSERT_MES(validate_tx_for_hardfork_specific_terms(tx, tx_id, bl_height), false, "tx " << tx_id << ": hardfork-specific validation failed");
TIME_MEASURE_START_PD(tx_process_extra);
- bool r = process_blockchain_tx_extra(tx, tx_id);
+ bool r = process_blockchain_tx_extra(tx, tx_id, bl_height);
CHECK_AND_ASSERT_MES(r, false, "failed to process_blockchain_tx_extra");
TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_process_extra);
@@ -4541,7 +4799,7 @@ bool blockchain_storage::add_transaction_from_block(const transaction& tx, const
{
LOG_ERROR("critical internal error: add_transaction_input_visitor failed. but key_images should be already checked");
purge_transaction_keyimages_from_blockchain(tx, false);
- bool r = unprocess_blockchain_tx_extra(tx);
+ bool r = unprocess_blockchain_tx_extra(tx, bl_height);
CHECK_AND_ASSERT_MES(r, false, "failed to unprocess_blockchain_tx_extra");
unprocess_blockchain_tx_attachments(tx, bl_height, timestamp);
@@ -4562,7 +4820,7 @@ bool blockchain_storage::add_transaction_from_block(const transaction& tx, const
{
LOG_ERROR("critical internal error: tx with id: " << tx_id << " in block id: " << bl_id << " already in blockchain");
purge_transaction_keyimages_from_blockchain(tx, true);
- bool r = unprocess_blockchain_tx_extra(tx);
+ bool r = unprocess_blockchain_tx_extra(tx, bl_height);
CHECK_AND_ASSERT_MES(r, false, "failed to unprocess_blockchain_tx_extra");
unprocess_blockchain_tx_attachments(tx, bl_height, timestamp);
@@ -5451,7 +5709,8 @@ uint64_t blockchain_storage::get_last_n_blocks_timestamps_median(size_t n) const
std::vector timestamps = get_last_n_blocks_timestamps(n);
uint64_t median_res = epee::misc_utils::median(timestamps);
- m_timestamps_median_cache[n] = median_res;
+ if (timestamps.size() == n)
+ m_timestamps_median_cache[n] = median_res;
return median_res;
}
//------------------------------------------------------------------
@@ -6967,7 +7226,7 @@ bool blockchain_storage::is_hardfork_active(size_t hardfork_id) const
//------------------------------------------------------------------
bool blockchain_storage::is_hardfork_active_for_height(size_t hardfork_id, uint64_t height) const
{
- return m_core_runtime_config.is_hardfork_active_for_height(hardfork_id, height);
+ return m_core_runtime_config.is_hardfork_active_for_height(hardfork_id, height != UINT64_MAX ? height : m_db_blocks.size());
}
//------------------------------------------------------------------
bool blockchain_storage::prevalidate_block(const block& bl)
diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h
index 9d7cba3a..78c75e66 100644
--- a/src/currency_core/blockchain_storage.h
+++ b/src/currency_core/blockchain_storage.h
@@ -381,7 +381,9 @@ namespace currency
const alt_chain_type& alt_chain = alt_chain_type(),
uint64_t split_height = 0)const;
bool validate_ado_ownership(asset_op_verification_context& avc) const;
- bool validate_asset_operation_against_current_blochain_state(asset_op_verification_context& avc) const;
+ bool validate_asset_operation_hf4(asset_op_verification_context& avc) const;
+ bool validate_asset_operation_hf5(asset_op_verification_context& avc) const;
+ bool validate_asset_operation(asset_op_verification_context& avc, uint64_t height) const;
void set_core_runtime_config(const core_runtime_config& pc) const;
const core_runtime_config& get_core_runtime_config()const;
@@ -679,14 +681,14 @@ namespace currency
uint64_t get_adjusted_time()const;
bool complete_timestamps_vector(uint64_t start_height, std::vector& timestamps);
bool update_next_comulative_size_limit();
- bool process_blockchain_tx_extra(const transaction& tx, const crypto::hash& tx_id);
- bool unprocess_blockchain_tx_extra(const transaction& tx);
+ bool process_blockchain_tx_extra(const transaction& tx, const crypto::hash& tx_id, const uint64_t height);
+ bool unprocess_blockchain_tx_extra(const transaction& tx, const uint64_t height);
bool process_blockchain_tx_attachments(const transaction& tx, uint64_t h, const crypto::hash& bl_id, uint64_t timestamp);
bool unprocess_blockchain_tx_attachments(const transaction& tx, uint64_t h, uint64_t timestamp);
bool pop_alias_info(const extra_alias_entry& ai);
bool put_alias_info(const transaction& tx, extra_alias_entry& ai);
- bool pop_asset_info(const crypto::public_key& asset_id);
- bool put_asset_info(const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado);
+ bool pop_asset_info(const asset_descriptor_operation& ado, const uint64_t height);
+ bool put_asset_info(const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado, const uint64_t height);
void fill_addr_to_alias_dict();
//bool resync_spent_tx_flags();
bool prune_ring_signatures_and_attachments_if_need();
diff --git a/src/currency_core/blockchain_storage_basic.h b/src/currency_core/blockchain_storage_basic.h
index 0013dc51..c15cdbe9 100644
--- a/src/currency_core/blockchain_storage_basic.h
+++ b/src/currency_core/blockchain_storage_basic.h
@@ -136,6 +136,7 @@ namespace currency
account_public_address stakeholder_address;
blobdata ex_nonce;
bool pos = false;
+ bool ignore_pow_ts_check = false;
pos_entry pe;
std::list explicit_txs;
fill_block_template_func_t *pcustom_fill_block_template_func;
diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h
index c6581611..d0630089 100644
--- a/src/currency_core/currency_basic.h
+++ b/src/currency_core/currency_basic.h
@@ -74,7 +74,9 @@ namespace currency
/************************************************************************/
/* */
/************************************************************************/
-
+
+ struct asset_descriptor_operation_v1;
+
//since structure used in blockchain as a key accessor, then be sure that there is no padding inside
#pragma pack(push, 1)
struct account_public_address_old
@@ -696,8 +698,20 @@ namespace currency
}
};
-#define ASSET_DESCRIPTOR_BASE_STRUCTURE_VER 1
+#define ASSET_DESCRIPTOR_BASE_HF4_VER 0
+#define ASSET_DESCRIPTOR_BASE_HF5_VER 2
+#define ASSET_DESCRIPTOR_BASE_LAST_VER 2
+ struct dummy
+ {
+ BEGIN_SERIALIZE()
+ END_SERIALIZE()
+
+ BEGIN_BOOST_SERIALIZATION()
+ END_BOOST_SERIALIZATION_TOTAL_FIELDS(0)
+ };
+
+ typedef boost::variant asset_descriptor_base_etc_fields;
typedef boost::variant asset_owner_pub_key_v;
struct asset_descriptor_base
@@ -710,11 +724,14 @@ namespace currency
std::string meta_info;
crypto::public_key owner = currency::null_pkey; // consider premultipling by 1/8
bool hidden_supply = false;
+ uint8_t version = ASSET_DESCRIPTOR_BASE_HF4_VER;
+ //version 1 members
boost::optional owner_eth_pub_key; // note: the size is 33 bytes (if present) // NOTE: using boost::optional instead of std::optional because of the Boost compilation issue: https://github.com/boostorg/serialization/issues/319 -- sowle
+ //version 2 members
+ std::vector etc; //container for future use if we would be adding some optional parameters that is not known yet, but without mess related to format version
- uint8_t version = ASSET_DESCRIPTOR_BASE_STRUCTURE_VER;
- BEGIN_VERSIONED_SERIALIZE(ASSET_DESCRIPTOR_BASE_STRUCTURE_VER, version)
+ BEGIN_VERSIONED_SERIALIZE(ASSET_DESCRIPTOR_BASE_LAST_VER, version)
FIELD(total_max_supply)
FIELD(current_supply)
FIELD(decimal_point)
@@ -725,8 +742,11 @@ namespace currency
FIELD(hidden_supply)
END_VERSION_UNDER(1)
FIELD(owner_eth_pub_key)
+ END_VERSION_UNDER(2)
+ FIELD(etc)
END_SERIALIZE()
+ BOOST_SERIALIZATION_CURRENT_ARCHIVE_VER(2)
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(total_max_supply)
BOOST_SERIALIZE(current_supply)
@@ -738,7 +758,10 @@ namespace currency
BOOST_SERIALIZE(hidden_supply)
BOOST_END_VERSION_UNDER(1)
BOOST_SERIALIZE(owner_eth_pub_key)
- END_BOOST_SERIALIZATION()
+ BOOST_END_VERSION_UNDER(2)
+ BOOST_SERIALIZE(etc)
+ BOOST_SERIALIZE(version)
+ END_BOOST_SERIALIZATION_TOTAL_FIELDS(11)
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(total_max_supply) DOC_DSCR("Maximum possible supply for a given asset, cannot be changed after deployment.") DOC_EXMP(1000000000000000000) DOC_END
@@ -778,38 +801,62 @@ namespace currency
#define ASSET_DESCRIPTOR_OPERATION_UPDATE 3
#define ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN 4
-#define ASSET_DESCRIPTOR_OPERATION_STRUCTURE_VER 1
+#define ASSET_DESCRIPTOR_OPERATION_HF4_VER 1
+#define ASSET_DESCRIPTOR_OPERATION_HF5_VER 2
+#define ASSET_DESCRIPTOR_OPERATION_LAST_VER 2
+
+ typedef boost::variant asset_descriptor_operation_etc_fields;
struct asset_descriptor_operation
{
- uint8_t operation_type = ASSET_DESCRIPTOR_OPERATION_UNDEFINED;
- asset_descriptor_base descriptor;
- crypto::public_key amount_commitment; // premultiplied by 1/8
- boost::optional opt_asset_id; // target asset_id - for update/emit
- uint8_t verion = ASSET_DESCRIPTOR_OPERATION_STRUCTURE_VER;
+ uint8_t operation_type = ASSET_DESCRIPTOR_OPERATION_UNDEFINED;
+ uint8_t version = ASSET_DESCRIPTOR_OPERATION_HF4_VER;
+ // register emit burn update
+ boost::optional opt_amount_commitment; // + + + - (premultiplied by 1/8)
+ boost::optional opt_asset_id; // - + + +
+ boost::optional opt_descriptor; // + - - +
+ boost::optional opt_amount; // ? ? ? - (only for non-hidden supply)
+ boost::optional opt_asset_id_salt; // ? - - - (optional)
+ std::vector etc; // (reserved for future use)
- BEGIN_VERSIONED_SERIALIZE(ASSET_DESCRIPTOR_OPERATION_STRUCTURE_VER, verion)
+
+ BEGIN_VERSIONED_SERIALIZE(ASSET_DESCRIPTOR_OPERATION_LAST_VER, version)
+ CHAIN_TRANSITION_VER(0, asset_descriptor_operation_v1)
+ CHAIN_TRANSITION_VER(1, asset_descriptor_operation_v1)
FIELD(operation_type)
- FIELD(descriptor)
- FIELD(amount_commitment)
- END_VERSION_UNDER(1)
+ FIELD(opt_amount_commitment)
FIELD(opt_asset_id)
+ FIELD(opt_descriptor)
+ FIELD(opt_amount)
+ FIELD(opt_asset_id_salt)
+ FIELD(etc)
END_SERIALIZE()
+ BOOST_SERIALIZATION_CURRENT_ARCHIVE_VER(2)
BEGIN_BOOST_SERIALIZATION()
+ BOOST_CHAIN_TRANSITION_VER(1, asset_descriptor_operation_v1)
+ BOOST_CHAIN_TRANSITION_VER(0, asset_descriptor_operation_v1)
+ BOOST_SERIALIZE(version)
BOOST_SERIALIZE(operation_type)
- BOOST_SERIALIZE(descriptor)
- BOOST_SERIALIZE(amount_commitment)
- BOOST_END_VERSION_UNDER(1)
+ BOOST_SERIALIZE(opt_amount_commitment)
BOOST_SERIALIZE(opt_asset_id)
- END_BOOST_SERIALIZATION()
+ BOOST_SERIALIZE(opt_descriptor)
+ BOOST_SERIALIZE(opt_amount)
+ BOOST_SERIALIZE(opt_asset_id_salt)
+ BOOST_SERIALIZE(etc)
+ END_BOOST_SERIALIZATION_TOTAL_FIELDS(8)
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(operation_type) DOC_DSCR("Asset operation type identifier") DOC_EXMP(1) DOC_END
- KV_SERIALIZE(descriptor) DOC_DSCR("Asset descriptor") DOC_EXMP_AUTO() DOC_END
- KV_SERIALIZE_POD_AS_HEX_STRING(amount_commitment) DOC_DSCR("Amount commitment") DOC_EXMP("f74bb56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END
- KV_SERIALIZE_POD_AS_HEX_STRING(opt_asset_id) DOC_DSCR("ID of an asset.") DOC_EXMP("cc4e69455e63f4a581257382191de6856c2156630b3fba0db4bdd73ffcfb36b6") DOC_END
+ KV_SERIALIZE(version) DOC_DSCR("Asset operation type struct version") DOC_EXMP(2) DOC_END
+ KV_SERIALIZE(operation_type) DOC_DSCR("Asset operation type identifier") DOC_EXMP(1) DOC_END
+ KV_SERIALIZE_POD_AS_HEX_STRING(opt_amount_commitment) DOC_DSCR("(optional) Asset operation amount commitment (register/emit/burn).") DOC_EXMP("5688b56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END
+ KV_SERIALIZE_POD_AS_HEX_STRING(opt_asset_id) DOC_DSCR("(optional) ID of an asset (emit/burn/update).") DOC_EXMP("cc4e69455e63f4a581257382191de6856c2156630b3fba0db4bdd73ffcfb36b6") DOC_END
+ KV_SERIALIZE(opt_descriptor) DOC_DSCR("(optional) Asset operation descriptor (register/update).") DOC_EXMP_AUTO() DOC_END
+ KV_SERIALIZE(opt_amount) DOC_DSCR("(optional) Asset operation amount (register/emit/burn when supply is non-hidden).") DOC_EXMP_AUTO() DOC_END
+ KV_SERIALIZE(opt_asset_id_salt) DOC_DSCR("(optional) Asset ID salt. May only be used for asset registration.") DOC_EXMP_AUTO() DOC_END
+ //KV_SERIALIZE(etc) DOC_DSCR("Extra operations") DOC_EXMP_AUTO() DOC_END <---- serialization for variant not supported yet
END_KV_SERIALIZE_MAP()
+
};
struct asset_operation_proof
@@ -824,6 +871,7 @@ namespace currency
FIELD(opt_amount_commitment_g_proof)
END_SERIALIZE()
+ BOOST_SERIALIZATION_CURRENT_ARCHIVE_VER(1)
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(opt_amount_commitment_composition_proof)
BOOST_SERIALIZE(opt_amount_commitment_g_proof)
@@ -842,6 +890,7 @@ namespace currency
FIELD(gss)
END_SERIALIZE()
+ BOOST_SERIALIZATION_CURRENT_ARCHIVE_VER(1)
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(gss)
BOOST_END_VERSION_UNDER(1)
@@ -1023,6 +1072,19 @@ namespace currency
FIELD(signatures)
FIELD(proofs)
END_SERIALIZE()
+
+
+ BOOST_SERIALIZATION_CURRENT_ARCHIVE_VER(0)
+ BEGIN_BOOST_SERIALIZATION()
+ BOOST_SERIALIZE(version)
+ BOOST_SERIALIZE(vin)
+ BOOST_SERIALIZE(vout)
+ BOOST_SERIALIZE(extra)
+ BOOST_SERIALIZE(signatures)
+ BOOST_SERIALIZE(attachment)
+ BOOST_END_VERSION_UNDER(1)
+ BOOST_SERIALIZE(proofs)
+ END_BOOST_SERIALIZATION()
};
@@ -1158,9 +1220,12 @@ BLOB_SERIALIZER(currency::txout_to_key);
VARIANT_TAG(json_archive, type_name, json_tag)
-BOOST_CLASS_VERSION(currency::asset_descriptor_operation, 1);
-BOOST_CLASS_VERSION(currency::asset_operation_proof, 1);
-BOOST_CLASS_VERSION(currency::asset_operation_ownership_proof, 1);
+
+LOOP_BACK_BOOST_SERIALIZATION_VERSION(currency::asset_descriptor_operation);
+LOOP_BACK_BOOST_SERIALIZATION_VERSION(currency::asset_descriptor_base);
+LOOP_BACK_BOOST_SERIALIZATION_VERSION(currency::asset_operation_proof);
+LOOP_BACK_BOOST_SERIALIZATION_VERSION(currency::asset_operation_ownership_proof);
+LOOP_BACK_BOOST_SERIALIZATION_VERSION(currency::transaction);
// txin_v variant currency
@@ -1235,7 +1300,8 @@ SET_VARIANT_TAGS(currency::asset_operation_ownership_proof, 51, "asset_operation
SET_VARIANT_TAGS(currency::asset_operation_ownership_proof_eth, 52, "asset_operation_ownership_proof_eth");
SET_VARIANT_TAGS(crypto::eth_public_key, 60, "eth_public_key");
-//SET_VARIANT_TAGS(crypto::eth_signature, 61, "eth_signature");s
+//SET_VARIANT_TAGS(crypto::eth_signature, 61, "eth_signature");
+SET_VARIANT_TAGS(currency::dummy, 62, "dummy");
diff --git a/src/currency_core/currency_basic_backward_comp.inl b/src/currency_core/currency_basic_backward_comp.inl
index 7dffea0e..9dc2a903 100644
--- a/src/currency_core/currency_basic_backward_comp.inl
+++ b/src/currency_core/currency_basic_backward_comp.inl
@@ -116,3 +116,74 @@ bool transition_convert(const transaction_v1& from, transaction_current_t& to)
}
return true;
}
+
+struct asset_descriptor_operation_v1
+{
+ uint8_t operation_type = ASSET_DESCRIPTOR_OPERATION_UNDEFINED;
+ asset_descriptor_base descriptor;
+ crypto::public_key amount_commitment = currency::null_pkey; // premultiplied by 1/8
+ boost::optional opt_asset_id; // target asset_id - for update/emit
+ uint8_t verion = ASSET_DESCRIPTOR_OPERATION_HF4_VER;
+
+ BEGIN_SERIALIZE()
+ FIELD(operation_type)
+ FIELD(descriptor)
+ FIELD(amount_commitment)
+ //END_VERSION_UNDER(1)
+ FIELD(opt_asset_id)
+ END_SERIALIZE()
+
+
+ //this map doesn't store internal version member, but it set it by default to val "1", which then transfered via transition_convert() to destination struct
+ BEGIN_BOOST_SERIALIZATION()
+ BOOST_SERIALIZE(operation_type)
+ BOOST_SERIALIZE(descriptor)
+ BOOST_SERIALIZE(amount_commitment)
+ //BOOST_END_VERSION_UNDER(1)
+ BOOST_SERIALIZE(opt_asset_id)
+ END_BOOST_SERIALIZATION()
+};
+
+template
+bool transition_convert(const asset_descriptor_operation_t& from, asset_descriptor_operation_v1& to)
+{
+ to.verion = from.version;
+ to.operation_type = from.operation_type;
+ if(from.opt_descriptor.has_value())
+ {
+ to.descriptor = *from.opt_descriptor;
+ }
+ else
+ {
+ throw std::runtime_error(std::string("Unexpected: missing descriptor in from transaction_current_t"));
+ }
+
+ if (from.opt_amount_commitment.has_value())
+ {
+ to.amount_commitment = *from.opt_amount_commitment;
+ }
+ else
+ {
+ //not used over update operations //throw std::runtime_error(std::string("Unexpected: missing amount_commitment in from transaction_current_t"));
+ }
+
+ to.opt_asset_id = from.opt_asset_id;
+
+ if(from.opt_amount.has_value() || from.etc.size())
+ {
+ throw std::runtime_error(std::string("Unexpected: opt_amount or etc have values during convention, looks like object slicing with information getting lost"));
+ }
+
+ return true;
+}
+
+template
+bool transition_convert(const asset_descriptor_operation_v1& from, asset_descriptor_operation_t& to)
+{
+ to.operation_type = from.operation_type;
+ to.opt_descriptor = from.descriptor;
+ to.opt_amount_commitment = from.amount_commitment;
+ to.opt_asset_id = from.opt_asset_id; // target asset_id - for update/emit
+ to.version = from.verion;
+ return true;
+}
\ No newline at end of file
diff --git a/src/currency_core/currency_boost_serialization.h b/src/currency_core/currency_boost_serialization.h
index 5d7c40f7..c12caf25 100644
--- a/src/currency_core/currency_boost_serialization.h
+++ b/src/currency_core/currency_boost_serialization.h
@@ -222,16 +222,7 @@ namespace boost
a & x.buff;
}
- template
- inline void serialize(Archive &a, currency::transaction &x, const boost::serialization::version_type ver)
- {
- a & x.version;
- a & x.vin;
- a & x.vout;
- a & x.extra;
- a & x.signatures;
- a & x.attachment;
- }
+
template
inline void serialize(Archive &a, currency::keypair &kp, const boost::serialization::version_type ver)
diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h
index ff666f50..1d6edf20 100644
--- a/src/currency_core/currency_config.h
+++ b/src/currency_core/currency_config.h
@@ -10,7 +10,7 @@
#ifndef TESTNET
#define CURRENCY_FORMATION_VERSION 84
#else
-#define CURRENCY_FORMATION_VERSION 98
+#define CURRENCY_FORMATION_VERSION 99
#endif
#define CURRENCY_GENESIS_NONCE (CURRENCY_FORMATION_VERSION + 101011010121) //bender's nightmare
@@ -118,7 +118,7 @@
#define P2P_MAINTAINERS_PUB_KEY "8f138bb73f6d663a3746a542770781a09579a7b84cb4125249e95530824ee607"
#define DIFFICULTY_POS_STARTER 1
#else
-#define P2P_DEFAULT_PORT (11112 + CURRENCY_FORMATION_VERSION)
+#define P2P_DEFAULT_PORT (11211 + CURRENCY_FORMATION_VERSION)
#define RPC_DEFAULT_PORT 12111
#define STRATUM_DEFAULT_PORT 11888
#define STRARUM_DEFAULT_PORT 51113
@@ -253,7 +253,7 @@
#define BC_OFFERS_CURRENCY_MARKET_FILENAME "market.bin"
-#define WALLET_FILE_SERIALIZATION_VERSION 167
+#define WALLET_FILE_SERIALIZATION_VERSION 168
#define WALLET_FILE_LAST_SUPPORTED_VERSION 165
#define CURRENT_MEMPOOL_ARCHIVE_VER (CURRENCY_FORMATION_VERSION+31)
@@ -271,16 +271,16 @@
#define ZANO_HARDFORK_04_AFTER_HEIGHT 2555000 // 2024-03-21 11:49:55
#define ZANO_HARDFORK_04_TIMESTAMP_ACTUAL 1711021795ull // block 2555000, 2024-03-21 11:49:55 UTC
#define ZANO_HARDFORK_05_AFTER_HEIGHT 999999999999999999
-#define ZANO_HARDFORK_05_MIN_BUILD_VER 343
+#define ZANO_HARDFORK_05_MIN_BUILD_VER 354
#else
// Testnet
#define ZANO_HARDFORK_01_AFTER_HEIGHT 0
#define ZANO_HARDFORK_02_AFTER_HEIGHT 0
#define ZANO_HARDFORK_03_AFTER_HEIGHT 0
-#define ZANO_HARDFORK_04_AFTER_HEIGHT 200
-#define ZANO_HARDFORK_04_TIMESTAMP_ACTUAL 1712785801ull // block 200, 2024-04-10 21:50:01 UTC
-#define ZANO_HARDFORK_05_AFTER_HEIGHT 241750
-#define ZANO_HARDFORK_05_MIN_BUILD_VER 343
+#define ZANO_HARDFORK_04_AFTER_HEIGHT 100
+#define ZANO_HARDFORK_04_TIMESTAMP_ACTUAL 1712800000ull // block 100, 2024-00-00 00:00:00 UTC
+#define ZANO_HARDFORK_05_AFTER_HEIGHT 200
+#define ZANO_HARDFORK_05_MIN_BUILD_VER 356
#endif
diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp
index 7df55765..96d55b46 100644
--- a/src/currency_core/currency_format_utils.cpp
+++ b/src/currency_core/currency_format_utils.cpp
@@ -197,17 +197,17 @@ namespace currency
return true;
}
//--------------------------------------------------------------------------------
- bool generate_zc_outs_range_proof(const crypto::hash& context_hash, size_t out_index_start, const tx_generation_context& outs_gen_context,
+ bool generate_zc_outs_range_proof(const crypto::hash& context_hash, const tx_generation_context& outs_gen_context,
const std::vector& vouts, zc_outs_range_proof& result)
{
size_t outs_count = outs_gen_context.amounts.size();
// TODO @#@# reconsider this check CHECK_AND_ASSERT_MES(gen_context.check_sizes(outs_count), false, "");
- CHECK_AND_ASSERT_MES(out_index_start + outs_count == vouts.size(), false, "");
+ CHECK_AND_ASSERT_MES(outs_count == vouts.size(), false, "");
// prepare data for aggregation proof
std::vector amount_commitments_for_rp_aggregation; // E' = amount * U + y' * G
crypto::scalar_vec_t y_primes; // y'
- for (size_t out_index = out_index_start, i = 0; i < outs_count; ++out_index, ++i)
+ for (size_t i = 0; i < outs_count; ++i)
{
crypto::scalar_t y_prime = crypto::scalar_t::random();
amount_commitments_for_rp_aggregation.emplace_back(outs_gen_context.amounts[i] * crypto::c_point_U + y_prime * crypto::c_point_G); // E'_j = e_j * U + y'_j * G
@@ -564,7 +564,7 @@ namespace currency
// range proofs
currency::zc_outs_range_proof range_proofs{};
- r = generate_zc_outs_range_proof(tx_id, 0, tx_gen_context, tx.vout, range_proofs);
+ r = generate_zc_outs_range_proof(tx_id, tx_gen_context, tx.vout, range_proofs);
CHECK_AND_ASSERT_MES(r, false, "Failed to generate zc_outs_range_proof()");
tx.proofs.emplace_back(std::move(range_proofs));
@@ -609,7 +609,7 @@ namespace currency
CHECK_AND_ASSERT_MES(count_type_in_variant_container(context.tx.proofs) == 1, false, "asset_operation_proof not present or present more than once");
const asset_operation_proof& aop = get_type_in_variant_container_by_ref(context.tx.proofs);
- if (context.ado.descriptor.hidden_supply)
+ if (context.ado.opt_descriptor.has_value() && context.ado.opt_descriptor->hidden_supply)
{
CHECK_AND_ASSERT_MES(aop.opt_amount_commitment_composition_proof.has_value(), false, "opt_amount_commitment_composition_proof is absent");
// TODO @#@# if asset is hidden -- check composition proof
@@ -619,7 +619,8 @@ namespace currency
{
// make sure that amount commitment corresponds to opt_amount_commitment_g_proof
CHECK_AND_ASSERT_MES(aop.opt_amount_commitment_g_proof.has_value(), false, "opt_amount_commitment_g_proof is absent");
- crypto::point_t A = crypto::point_t(context.ado.amount_commitment).modify_mul8() - context.amount_to_validate * context.asset_id_pt;
+ CHECK_AND_ASSERT_MES(context.ado.opt_amount_commitment.has_value(), false, "amount_commitment is absent");
+ crypto::point_t A = crypto::point_t(context.ado.opt_amount_commitment.get()).modify_mul8() - context.amount_to_validate * context.asset_id_pt;
bool r = crypto::check_signature(context.tx_id, A.to_public_key(), aop.opt_amount_commitment_g_proof.get());
CHECK_AND_ASSERT_MES(r, false, "opt_amount_commitment_g_proof check failed");
@@ -675,12 +676,14 @@ namespace currency
{
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT)
{
+ CHECK_AND_ASSERT_MES(ado.opt_amount_commitment.has_value(), false, "opt_amount_commitment is missing");
// amount_commitment supposed to be validated earlier in validate_asset_operation_amount_commitment()
- sum_of_pseudo_out_amount_commitments += crypto::point_t(ado.amount_commitment); // *1/8
+ sum_of_pseudo_out_amount_commitments += crypto::point_t(ado.opt_amount_commitment.get()); // *1/8
}
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
{
- outs_commitments_sum += crypto::point_t(ado.amount_commitment); // *1/8
+ CHECK_AND_ASSERT_MES(ado.opt_amount_commitment.has_value(), false, "opt_amount_commitment is missing");
+ outs_commitments_sum += crypto::point_t(ado.opt_amount_commitment.get()); // *1/8
}
}
size_t zc_sigs_count = 0;
@@ -2186,18 +2189,23 @@ namespace currency
// otherwise, it must be a register operation
CHECK_AND_ASSERT_MES(ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER, false, "unexpected asset operation type: " << (int)ado.operation_type << ", " << get_asset_operation_type_string(ado.operation_type));
+ CHECK_AND_ASSERT_MES(ado.opt_descriptor.has_value(), false, "opt_descriptor is missing: " << (int)ado.operation_type << ", " << get_asset_operation_type_string(ado.operation_type));
+ const asset_descriptor_base &adb = ado.opt_descriptor.get();
// calculate asset id
crypto::hash_helper_t::hs_t hsc;
hsc.add_32_chars(CRYPTO_HDS_ASSET_ID);
- hsc.add_hash(crypto::hash_helper_t::h(ado.descriptor.ticker));
- hsc.add_hash(crypto::hash_helper_t::h(ado.descriptor.full_name));
- hsc.add_hash(crypto::hash_helper_t::h(ado.descriptor.meta_info));
- hsc.add_scalar(crypto::scalar_t(ado.descriptor.total_max_supply));
- hsc.add_scalar(crypto::scalar_t(ado.descriptor.decimal_point));
- hsc.add_pub_key(ado.descriptor.owner);
- if (ado.descriptor.owner_eth_pub_key.has_value())
- hsc.add_eth_pub_key(ado.descriptor.owner_eth_pub_key.value());
+ hsc.add_hash(crypto::hash_helper_t::h(adb.ticker));
+ hsc.add_hash(crypto::hash_helper_t::h(adb.full_name));
+ hsc.add_hash(crypto::hash_helper_t::h(adb.meta_info));
+ hsc.add_scalar(crypto::scalar_t(adb.total_max_supply));
+ hsc.add_scalar(crypto::scalar_t(adb.decimal_point));
+ hsc.add_pub_key(adb.owner);
+ if (adb.owner_eth_pub_key.has_value())
+ hsc.add_eth_pub_key(adb.owner_eth_pub_key.value());
+ if (ado.opt_asset_id_salt.has_value())
+ hsc.add_scalar(crypto::scalar_t(ado.opt_asset_id_salt.get()));
+
crypto::hash h = hsc.calc_hash_no_reduce();
// this hash function needs to be computationally expensive (s.a. the whitepaper)
@@ -2242,16 +2250,11 @@ namespace currency
{
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
{
- //crypto::secret_key asset_control_key{};
- //bool r = derive_key_pair_from_key_pair(sender_account_keys.account_address.spend_public_key, tx_key.sec, asset_control_key, ado.descriptor.owner, CRYPTO_HDS_ASSET_CONTROL_KEY);
- //CHECK_AND_ASSERT_MES(r, false, "derive_key_pair_from_key_pair failed");
- //
- // old:
- // asset_control_key = Hs(CRYPTO_HDS_ASSET_CONTROL_KEY, 8 * tx_key.sec * sender_account_keys.account_address.spend_public_key, 0)
- // ado.descriptor.owner = asset_control_key * G
+ CHECK_AND_ASSERT_MES(ado.opt_descriptor.has_value(), false, "opt_descriptor is missing (register)");
+ asset_descriptor_base& adb = ado.opt_descriptor.get();
- if (!ado.descriptor.owner_eth_pub_key.has_value())
- ado.descriptor.owner = sender_account_keys.account_address.spend_public_key;
+ if (!adb.owner_eth_pub_key.has_value())
+ adb.owner = sender_account_keys.account_address.spend_public_key;
CHECK_AND_ASSERT_MES(get_or_calculate_asset_id(ado, &gen_context.ao_asset_id_pt, &gen_context.ao_asset_id), false, "get_or_calculate_asset_id failed");
@@ -2268,10 +2271,14 @@ namespace currency
amount_of_emitted_asset += item.amount;
}
}
- ado.descriptor.current_supply = amount_of_emitted_asset; // TODO: consider setting current_supply beforehand, not setting it hear in ad-hoc manner -- sowle
+ adb.current_supply = amount_of_emitted_asset;
+ if (ado.version >= ASSET_DESCRIPTOR_BASE_HF5_VER)
+ {
+ ado.opt_amount = amount_of_emitted_asset; // TODO: support hidden supply -- sowle
+ }
gen_context.ao_amount_commitment = amount_of_emitted_asset * gen_context.ao_asset_id_pt + gen_context.ao_amount_blinding_mask * crypto::c_point_G;
- ado.amount_commitment = (crypto::c_scalar_1div8 * gen_context.ao_amount_commitment).to_public_key();
+ ado.opt_amount_commitment = (crypto::c_scalar_1div8 * gen_context.ao_amount_commitment).to_public_key();
}
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
{
@@ -2281,7 +2288,7 @@ namespace currency
gen_context.ao_amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_ASSET_CONTROL_ABM, tx_key.sec);
gen_context.ao_commitment_in_outputs = true;
- // set correct asset_id to the corresponding destination entries
+ // calculate the amount of asset being burnt using asset_id field in inputs and outputs (sources and destinations)
uint64_t amount_of_burned_assets = 0;
for (auto& item : ftp.sources)
{
@@ -2298,10 +2305,19 @@ namespace currency
amount_of_burned_assets -= item.amount;
}
}
- ado.descriptor.current_supply -= amount_of_burned_assets;
-
+ if (ado.version < ASSET_DESCRIPTOR_BASE_HF5_VER)
+ {
+ CHECK_AND_ASSERT_THROW_MES(ado.opt_descriptor.has_value(), "Internal error: opt_descriptor unset during ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN for version less then 2");
+ ado.opt_descriptor->current_supply -= amount_of_burned_assets;
+ }
+ else
+ {
+ CHECK_AND_ASSERT_THROW_MES(!ado.opt_descriptor.has_value(), "Internal error: opt_descriptor unset during ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN for version less then 2");
+ ado.opt_amount = amount_of_burned_assets; // TODO: support hidden supply -- sowle
+ }
+
gen_context.ao_amount_commitment = amount_of_burned_assets * gen_context.ao_asset_id_pt + gen_context.ao_amount_blinding_mask * crypto::c_point_G;
- ado.amount_commitment = (crypto::c_scalar_1div8 * gen_context.ao_amount_commitment).to_public_key();
+ ado.opt_amount_commitment = (crypto::c_scalar_1div8 * gen_context.ao_amount_commitment).to_public_key();
if (ftp.pevents_dispatcher) ftp.pevents_dispatcher->RAISE_DEBUG_EVENT(wde_construct_tx_handle_asset_descriptor_operation_before_burn{ &ado });
@@ -2325,10 +2341,19 @@ namespace currency
item.asset_id = gen_context.ao_asset_id;
}
}
- ado.descriptor.current_supply += amount_of_emitted_asset;
+ if (ado.version < ASSET_DESCRIPTOR_BASE_HF5_VER)
+ {
+ CHECK_AND_ASSERT_THROW_MES(ado.opt_descriptor.has_value(), "Internal error: opt_descriptor unset during ASSET_DESCRIPTOR_OPERATION_EMIT for version less then 2");
+ ado.opt_descriptor->current_supply += amount_of_emitted_asset;
+ }
+ else
+ {
+ CHECK_AND_ASSERT_THROW_MES(!ado.opt_descriptor.has_value(), "Internal error: opt_descriptor unset during ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN for version less then 2");
+ ado.opt_amount = amount_of_emitted_asset; // TODO: support hidden supply -- sowle
+ }
gen_context.ao_amount_commitment = amount_of_emitted_asset * gen_context.ao_asset_id_pt + gen_context.ao_amount_blinding_mask * crypto::c_point_G;
- ado.amount_commitment = (crypto::c_scalar_1div8 * gen_context.ao_amount_commitment).to_public_key();
+ ado.opt_amount_commitment = (crypto::c_scalar_1div8 * gen_context.ao_amount_commitment).to_public_key();
}
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE)
@@ -2607,7 +2632,6 @@ namespace currency
// construct outputs
uint64_t native_coins_output_sum = 0;
size_t output_index = tx.vout.size(); // in case of append mode we need to start output indexing from the last one + 1
- uint64_t range_proof_start_index = 0;
std::set existing_derivation_hints, new_derivation_hints;
CHECK_AND_ASSERT_MES(copy_all_derivation_hints_from_tx_to_container(tx, existing_derivation_hints), false, "move_all_derivation_hints_from_tx_to_container failed");
for(size_t destination_index = 0; destination_index < shuffled_dsts.size(); ++destination_index, ++output_index)
@@ -2749,7 +2773,7 @@ namespace currency
// range proofs
currency::zc_outs_range_proof range_proofs{};
- r = generate_zc_outs_range_proof(tx_prefix_hash, range_proof_start_index, gen_context, tx.vout, range_proofs);
+ r = generate_zc_outs_range_proof(tx_prefix_hash, gen_context, tx.vout, range_proofs);
CHECK_AND_ASSERT_MES(r, false, "Failed to generate zc_outs_range_proof()");
tx.proofs.emplace_back(std::move(range_proofs));
@@ -2774,8 +2798,7 @@ namespace currency
const asset_descriptor_operation* pado = get_type_in_variant_container(tx.extra);
if (pado != nullptr)
{
- if ((pado->operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT || pado->operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE) &&
- !pado->descriptor.owner_eth_pub_key.has_value())
+ if ((pado->operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT || pado->operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE) && (!ftp.ado_sign_thirdparty))
{
asset_operation_ownership_proof aoop{};
r = crypto::generate_schnorr_sig(tx_prefix_hash, sender_account_keys.spend_secret_key, aoop.gss);
@@ -3609,13 +3632,13 @@ namespace currency
return true;
}
//------------------------------------------------------------------
+ #define PASSWORD_REGEXP R"([A-Za-z0-9~!?@#$%^&*_+|{}\[\]()<>:;"'\-=/.,]{0,40})"
bool validate_password(const std::string& password)
{
- static const std::string allowed_password_symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!?@#$%^&*_+|{}[]()<>:;\"'-=\\/.,";
- size_t n = password.find_first_not_of(allowed_password_symbols, 0);
- return n == std::string::npos;
+ // OLD: static const std::string allowed_password_symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!?@#$%^&*_+|{}[]()<>:;\"'-=\\/.,";
+ static std::regex password_regexp(PASSWORD_REGEXP);
+ return std::regex_match(password, password_regexp);
}
-
//------------------------------------------------------------------
#define ANTI_OVERFLOW_AMOUNT 1000000
#define GET_PERECENTS_BIG_NUMBERS(per, total) (per/ANTI_OVERFLOW_AMOUNT)*100 / (total/ANTI_OVERFLOW_AMOUNT)
@@ -4442,8 +4465,8 @@ namespace currency
}
}
//------------------------------------------------------------------
-#define ASSET_TICKER_REGEXP "[A-Za-z0-9]{1,14}"
-#define ASSET_FULL_NAME_REGEXP "[A-Za-z0-9.,:!?\\-() ]{0,400}"
+#define ASSET_TICKER_REGEXP R"([A-Za-z0-9]{1,14})"
+#define ASSET_FULL_NAME_REGEXP R"([A-Za-z0-9.,:!?\-() ]{0,400})"
bool validate_asset_ticker(const std::string& ticker)
{
static std::regex asset_ticker_regexp(ASSET_TICKER_REGEXP);
diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h
index 2fab77e1..399a6d90 100644
--- a/src/currency_core/currency_format_utils.h
+++ b/src/currency_core/currency_format_utils.h
@@ -29,6 +29,7 @@
#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"
#include "bc_attachments_helpers.h"
#include "bc_payments_id_service.h"
#include "bc_offers_service_basic.h"
@@ -164,9 +165,11 @@ namespace currency
uint64_t tx_version;
uint64_t mode_separate_fee = 0;
- epee::misc_utils::events_dispatcher* pevents_dispatcher;
+ epee::misc_utils::events_dispatcher* pevents_dispatcher = nullptr;
tx_generation_context gen_context{}; // solely for consolidated txs
+
+ bool ado_sign_thirdparty = false;//@#@ TODO: add to serialization map @zoidberg
BEGIN_SERIALIZE_OBJECT()
@@ -259,6 +262,7 @@ namespace currency
const transaction& tx;
const crypto::hash& tx_id;
const asset_descriptor_operation& ado;
+ uint64_t height = UINT64_MAX; // default value means the height of the upcoming block (top_block + 1)
crypto::public_key asset_id = currency::null_pkey;
crypto::point_t asset_id_pt = crypto::c_point_0;
uint64_t amount_to_validate = 0;
@@ -269,7 +273,7 @@ namespace currency
bool generate_asset_surjection_proof(const crypto::hash& context_hash, bool has_non_zc_inputs, tx_generation_context& ogc, zc_asset_surjection_proof& result);
bool verify_asset_surjection_proof(const transaction& tx, const crypto::hash& tx_id);
bool generate_tx_balance_proof(const transaction &tx, const crypto::hash& tx_id, const tx_generation_context& ogc, uint64_t block_reward_for_miner_tx, zc_balance_proof& proof);
- bool generate_zc_outs_range_proof(const crypto::hash& context_hash, size_t out_index_start, const tx_generation_context& outs_gen_context,
+ bool generate_zc_outs_range_proof(const crypto::hash& context_hash, const tx_generation_context& outs_gen_context,
const std::vector& vouts, zc_outs_range_proof& result);
bool check_tx_bare_balance(const transaction& tx, uint64_t additional_inputs_amount_and_fees_for_mining_tx = 0);
bool check_tx_balance(const transaction& tx, const crypto::hash& tx_id, uint64_t additional_inputs_amount_and_fees_for_mining_tx = 0);
@@ -950,6 +954,7 @@ namespace currency
}
}
}
+ /*
//---------------------------------------------------------------
template
typename std::enable_if_t, std::ostream&> operator<<(std::ostream& o, invocable_t callee)
@@ -957,6 +962,7 @@ namespace currency
callee(o);
return o;
}
+ */
//---------------------------------------------------------------
std::ostream& operator <<(std::ostream& o, const ref_by_id& r);
std::ostream& operator <<(std::ostream& o, const std::type_info& ti);
@@ -1214,7 +1220,13 @@ namespace currency
tv.short_view = std::string("op:") + get_asset_operation_type_string(ado.operation_type, true);
if (ado.opt_asset_id.has_value())
tv.short_view += std::string(" , id:") + crypto::pod_to_hex(ado.opt_asset_id);
- tv.details_view = tv.short_view + std::string(" , ticker:") + ado.descriptor.ticker + std::string(" , cur.supply:") + print_money_brief(ado.descriptor.current_supply, ado.descriptor.decimal_point);
+ tv.details_view = tv.short_view;
+ if (ado.opt_descriptor.has_value())
+ {
+ tv.details_view += std::string(" , ticker:") + ado.opt_descriptor->ticker + std::string(" , cur.supply:") + print_money_brief(ado.opt_descriptor->current_supply, ado.opt_descriptor->decimal_point);
+ }
+ //@#@ TODO: add other info from asset_descriptor_operation v2+
+
return true;
}
template
diff --git a/src/currency_core/miner.cpp b/src/currency_core/miner.cpp
index d52e51e2..109d9966 100644
--- a/src/currency_core/miner.cpp
+++ b/src/currency_core/miner.cpp
@@ -40,24 +40,25 @@ namespace currency
}
- miner::miner(i_miner_handler* phandler, blockchain_storage& bc):m_stop(1),
- //m_bc(bc),
- m_template(boost::value_initialized()),
- m_template_no(0),
- m_diffic(0),
- m_thread_index(0),
- m_phandler(phandler),
- m_height(0),
- m_pausers_count(0),
- m_threads_total(0),
- m_starter_nonce(0),
- m_do_print_hashrate(false),
- m_do_mining(false),
- m_current_hash_rate(0),
- m_last_hr_merge_time(0),
- m_hashes(0),
- m_config(AUTO_VAL_INIT(m_config)),
- m_mine_address{}
+ miner::miner(i_miner_handler* phandler, blockchain_storage& bc)
+ : m_stop(1)
+ , m_template(boost::value_initialized())
+ , m_template_no(0)
+ , m_diffic(0)
+ , m_thread_index(0)
+ , m_phandler(phandler)
+ , m_height(0)
+ , m_pausers_count(0)
+ , m_block_template_ready(false)
+ , m_threads_total(0)
+ , m_starter_nonce(0)
+ , m_do_print_hashrate(false)
+ , m_do_mining(false)
+ , m_current_hash_rate(0)
+ , m_last_hr_merge_time(0)
+ , m_hashes(0)
+ , m_config(AUTO_VAL_INIT(m_config))
+ , m_mine_address{}
{
}
//-----------------------------------------------------------------------------------------------------
@@ -76,6 +77,7 @@ namespace currency
m_height = height;
++m_template_no;
m_starter_nonce = crypto::rand();
+ m_block_template_ready = true;
return true;
}
//-----------------------------------------------------------------------------------------------------
@@ -100,7 +102,8 @@ namespace currency
}
if(!m_phandler->get_block_template(bl, m_mine_address, m_mine_address, di, height, extra_nonce))
{
- LOG_ERROR("Failed to get_block_template()");
+ // it's quite possible that block template cannot be created at particular time; need to wait
+ m_block_template_ready = false;
return false;
}
set_block_template(bl, di, height);
@@ -110,7 +113,8 @@ namespace currency
bool miner::on_idle()
{
m_update_block_template_interval.do_call([&](){
- if(is_mining())request_block_template();
+ if(is_mining())
+ request_block_template();
return true;
});
@@ -233,8 +237,13 @@ namespace currency
return false;
}
- if(!m_template_no)
- request_block_template();//lets update block template
+ while(!m_template_no)
+ {
+ if (request_block_template())
+ break;
+ std::this_thread::sleep_for(std::chrono::seconds(2));
+ LOG_PRINT_L1("Trying to get block template....");
+ }
boost::interprocess::ipcdetail::atomic_write32(&m_stop, 0);
boost::interprocess::ipcdetail::atomic_write32(&m_thread_index, 0);
@@ -313,12 +322,11 @@ namespace currency
uint64_t local_height = 0;
crypto::hash local_blob_data_hash = null_hash;
- //uint64_t local_template_height = 0;
- block b;
+ block b{};
while(!m_stop)
{
- if(m_pausers_count)//anti split workaround
+ if(m_pausers_count != 0 || !m_block_template_ready)
{
misc_utils::sleep_no_w(100);
continue;
diff --git a/src/currency_core/miner.h b/src/currency_core/miner.h
index 94caea2b..c8a37225 100644
--- a/src/currency_core/miner.h
+++ b/src/currency_core/miner.h
@@ -101,6 +101,7 @@ namespace currency
volatile uint32_t m_thread_index;
volatile uint32_t m_threads_total;
std::atomic m_pausers_count;
+ std::atomic m_block_template_ready;
epee::critical_section m_miners_count_lock;
std::list m_threads;
diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp
index 33315870..d076d147 100644
--- a/src/currency_core/tx_pool.cpp
+++ b/src/currency_core/tx_pool.cpp
@@ -247,7 +247,7 @@ namespace currency
r = process_type_in_variant_container_and_make_sure_its_unique(tx.extra, [&](const asset_descriptor_operation& ado){
asset_op_verification_context avc = { tx, id, ado };
- return m_blockchain.validate_asset_operation_against_current_blochain_state(avc);
+ return m_blockchain.validate_asset_operation(avc, m_blockchain.get_current_blockchain_size());
}, true);
CHECK_AND_ASSERT_MES_CUSTOM(r, false, { tvc.m_verification_failed = true; }, "post-HF4 tx: asset operation is invalid");
}
diff --git a/src/daemon/daemon_commands_handler.h b/src/daemon/daemon_commands_handler.h
index c960a39c..1b26fb73 100644
--- a/src/daemon/daemon_commands_handler.h
+++ b/src/daemon/daemon_commands_handler.h
@@ -48,6 +48,7 @@ public:
m_cmd_binder.set_handler("print_tx_prun_info", boost::bind(&daemon_commands_handler::print_tx_prun_info, this, ph::_1), "Print tx prunning info");
m_cmd_binder.set_handler("print_tx", boost::bind(&daemon_commands_handler::print_tx, this, ph::_1), "Print transaction, print_tx ");
m_cmd_binder.set_handler("print_asset_info", boost::bind(&daemon_commands_handler::print_asset_info, this, ph::_1), "Print information about the given asset by its id");
+ m_cmd_binder.set_handler("print_blocked_ips", boost::bind(&daemon_commands_handler::print_blocked_ips, this, ph::_1), "Print ip address blacklists");
m_cmd_binder.set_handler("start_mining", boost::bind(&daemon_commands_handler::start_mining, this, ph::_1), "Start mining for specified address, start_mining [threads=1]");
m_cmd_binder.set_handler("stop_mining", boost::bind(&daemon_commands_handler::stop_mining, this, ph::_1), "Stop mining");
m_cmd_binder.set_handler("print_pool", boost::bind(&daemon_commands_handler::print_pool, this, ph::_1), "Print transaction pool (long format)");
@@ -235,6 +236,20 @@ private:
return true;
}
//--------------------------------------------------------------------------------
+ bool print_blocked_ips(const std::vector& args)
+ {
+ std::map blocklist;
+ m_srv.get_ip_block_list(blocklist);
+ std::stringstream ss;
+ ss << "BLOCKED IPS:" << ENDL;
+ for (const auto& e : blocklist)
+ {
+ ss << string_tools::get_ip_string_from_int32(e.first) << ", time: " << std::put_time(std::localtime(&e.second), "%Y-%m-%d %H:%M:%S") << ENDL;
+ }
+ LOG_PRINT_L0(ss.str());
+ return true;
+ }
+ //--------------------------------------------------------------------------------
bool print_bc(const std::vector& args)
{
if (!args.size())
@@ -806,17 +821,21 @@ private:
size_t idx = 0;
for(auto& aop: asset_history)
{
- ss << "[" << std::setw(2) << idx << "] operation: " << currency::get_asset_operation_type_string(aop.operation_type) << " (" << (int)aop.operation_type << ")" << ENDL <<
- " ticker: \"" << aop.descriptor.ticker << "\"" << ENDL <<
- " full name: \"" << aop.descriptor.full_name << "\"" << ENDL <<
- " meta info: \"" << aop.descriptor.meta_info << "\"" << ENDL <<
- " current supply: " << currency::print_money_brief(aop.descriptor.current_supply, aop.descriptor.decimal_point) << ENDL <<
- " max supply: " << currency::print_money_brief(aop.descriptor.total_max_supply, aop.descriptor.decimal_point) << ENDL <<
- " decimal point: " << (int)aop.descriptor.decimal_point << ENDL <<
- " owner * 1/8: " << aop.descriptor.owner << ENDL <<
- " amount cmt * 1/8: " << aop.amount_commitment << ENDL <<
- " hidden supply: " << (aop.descriptor.hidden_supply ? "yes" : "no") << ENDL <<
- "";
+ if (aop.opt_descriptor.has_value())
+ {
+ const currency::asset_descriptor_base& adb = aop.opt_descriptor.value();
+ ss << "[" << std::setw(2) << idx << "] operation: " << currency::get_asset_operation_type_string(aop.operation_type) << " (" << (int)aop.operation_type << ")" << ENDL <<
+ " ticker: \"" << adb.ticker << "\"" << ENDL <<
+ " full name: \"" << adb.full_name << "\"" << ENDL <<
+ " meta info: \"" << adb.meta_info << "\"" << ENDL <<
+ " current supply: " << currency::print_money_brief(adb.current_supply, adb.decimal_point) << ENDL <<
+ " max supply: " << currency::print_money_brief(adb.total_max_supply, adb.decimal_point) << ENDL <<
+ " decimal point: " << (int)adb.decimal_point << ENDL <<
+ " owner * 1/8: " << adb.owner << ENDL <<
+ " amount cmt * 1/8: " << (aop.opt_amount_commitment.has_value() ? aop.opt_amount_commitment.value() : currency::null_pkey) << ENDL <<
+ " hidden supply: " << (adb.hidden_supply ? "yes" : "no") << ENDL <<
+ "";
+ }
++idx;
}
diff --git a/src/gui/qt-daemon/layout b/src/gui/qt-daemon/layout
index 5c878005..7cd0e5e5 160000
--- a/src/gui/qt-daemon/layout
+++ b/src/gui/qt-daemon/layout
@@ -1 +1 @@
-Subproject commit 5c878005ace55484eafe2985d204cd51e90b203b
+Subproject commit 7cd0e5e54a0d692ea819b9653f60a1cd5512dc2b
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index 9ec3cc17..38b5a5ab 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -121,6 +121,7 @@ namespace nodetool
peerlist_manager& get_peerlist_manager(){return m_peerlist;}
bool handle_maintainers_entry(const maintainers_entry& me);
bool get_maintainers_info(maintainers_info_external& me);
+ void get_ip_block_list(std::map& blocklist);
typedef COMMAND_REQUEST_STAT_INFO_T COMMAND_REQUEST_STAT_INFO;
private:
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 70b906dc..fb1c4109 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -448,6 +448,13 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template
+ void node_server::get_ip_block_list(std::map& blocklist)
+ {
+ CRITICAL_REGION_LOCAL(m_blocked_ips_lock);
+ blocklist = m_blocked_ips;
+ }
+ //-----------------------------------------------------------------------------------
+ template
bool node_server::on_maintainers_entry_update()
{
LOG_PRINT_CHANNEL_COLOR2(NULL, NULL, "Fresh maintainers info recieved(timestamp: " << m_maintainers_info_local.timestamp << ")", LOG_LEVEL_0, epee::log_space::console_color_magenta);
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 7960328f..9a5d07e2 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -591,6 +591,12 @@ bool simple_wallet::try_connect_to_daemon()
//----------------------------------------------------------------------------------------------------
bool simple_wallet::new_wallet(const string &wallet_file, const std::string& password, bool create_auditable_wallet)
{
+ if (!currency::validate_password(password))
+ {
+ fail_msg_writer() << R"(Provided password contains invalid characters. Only letters, numbers and ~!?@#$%^&*_+|{}[]()<>:;"'-=/., symbols are allowed.)" << ENDL;
+ return false;
+ }
+
m_wallet_file = wallet_file;
m_wallet.reset(new tools::wallet2());
@@ -1202,7 +1208,7 @@ bool simple_wallet::show_staking_history(const std::vector& args)
bool transfers_found = false;
for (auto it = transfers.rbegin(); it != transfers.rend(); it++)
{
- const auto& td = *it;
+ const auto& td = it->second;
if (timestamp && td.m_ptx_wallet_info->m_block_timestamp < timestamp)
break;
@@ -1264,8 +1270,9 @@ bool simple_wallet::show_incoming_transfers(const std::vector& args
m_wallet->get_transfers(transfers);
bool transfers_found = false;
- for (const auto& td : transfers)
+ for (const auto& tr : transfers)
{
+ const auto& td = tr.second;
if (!filter || available != static_cast(td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_SPENT))
{
if (!transfers_found)
@@ -1308,8 +1315,9 @@ bool simple_wallet::show_incoming_transfers_counts(const std::vector &args)
fail_msg_writer() << "Failed to load json file with asset specification: " << args[0];
return true;
}
+
+ if (!validate_asset_ticker_and_full_name(adb))
+ {
+ fail_msg_writer() << "ticker or full_name are invalid (perhaps they contain invalid symbols)";
+ return true;
+ }
+
tx_destination_entry td = AUTO_VAL_INIT(td);
td.addr.push_back(m_wallet->get_account().get_public_address());
td.amount = adb.current_supply;
@@ -3140,7 +3155,7 @@ int wmain( int argc, wchar_t* argv_w[ ], wchar_t* envp[ ] )
int main(int argc, char* argv[])
#endif
{
-#ifdef WIN32
+#if defined(WIN32) && defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
//_CrtSetBreakAlloc(9594);
#endif
@@ -3472,7 +3487,7 @@ int main(int argc, char* argv[])
//runs wallet with console interface
sw->set_offline_mode(offline_mode);
r = sw->init(vm);
- CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize wallet");
+ CHECK_AND_ASSERT_MES(r, EXIT_FAILURE, "Failed to initialize wallet");
if (command_line::get_arg(vm, arg_generate_new_wallet).size() || command_line::get_arg(vm, arg_generate_new_auditable_wallet).size())
return EXIT_FAILURE;
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index 5f260433..d8bbb5d8 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -29,7 +29,7 @@ namespace currency
typedef std::vector command_type;
simple_wallet();
- ~simple_wallet();
+ virtual ~simple_wallet();
bool init(const boost::program_options::variables_map& vm);
bool deinit();
bool run();
diff --git a/src/version.h.in b/src/version.h.in
index 1c544210..09597591 100644
--- a/src/version.h.in
+++ b/src/version.h.in
@@ -8,6 +8,6 @@
#define PROJECT_REVISION "1"
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
-#define PROJECT_VERSION_BUILD_NO 352
+#define PROJECT_VERSION_BUILD_NO 366
#define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO)
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]"
diff --git a/src/wallet/core_default_rpc_proxy.cpp b/src/wallet/core_default_rpc_proxy.cpp
index 4bd94188..38907e37 100644
--- a/src/wallet/core_default_rpc_proxy.cpp
+++ b/src/wallet/core_default_rpc_proxy.cpp
@@ -20,7 +20,11 @@ namespace tools
{
bool default_http_core_proxy::set_connection_addr(const std::string& url)
{
- m_daemon_address = url;
+ if (m_daemon_address != url)
+ {
+ m_daemon_address = url;
+ m_http_client.disconnect();
+ }
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
diff --git a/src/wallet/plain_wallet_api.cpp b/src/wallet/plain_wallet_api.cpp
index 3a9a1552..bb322481 100644
--- a/src/wallet/plain_wallet_api.cpp
+++ b/src/wallet/plain_wallet_api.cpp
@@ -56,6 +56,9 @@ void static_destroy_handler()
LOG_PRINT_L0("[DESTROY CALLBACK HANDLER FINISHED]: ");
}
+
+
+
namespace plain_wallet
{
struct plain_wallet_instance
@@ -63,7 +66,9 @@ namespace plain_wallet
plain_wallet_instance() :initialized(false), gjobs_counter(1)
{}
wallets_manager gwm;
- std::atomic initialized;
+ std::atomic initialized = false;
+ std::atomic postponed_run_wallet = false;
+ std::atomic postponed_main_worked_started = false;
std::atomic gjobs_counter;
std::map gjobs;
@@ -73,7 +78,6 @@ namespace plain_wallet
std::shared_ptr ginstance_ptr;
-
typedef epee::json_rpc::response error_response;
@@ -182,8 +186,11 @@ namespace plain_wallet
}
- std::string init(const std::string& ip, const std::string& port, const std::string& working_dir, int log_level)
+ std::string init(const std::string& ip_, const std::string& port_, const std::string& working_dir, int log_level)
{
+ std::string ip = ip_;
+ std::string port = port_;
+
auto local_ptr = std::atomic_load(&ginstance_ptr);
if (local_ptr)
{
@@ -197,6 +204,14 @@ namespace plain_wallet
std::shared_ptr ptr(new plain_wallet_instance());
+ if (ip.empty())
+ {
+ ip = "0.0.0.0";
+ port = "0";
+ ptr->postponed_run_wallet = true;
+ }
+
+
set_bundle_working_dir(working_dir);
initialize_logs(log_level);
@@ -217,10 +232,14 @@ namespace plain_wallet
ptr->gwm.set_use_deffered_global_outputs(true);
- if(!ptr->gwm.start())
+ if (!ptr->postponed_run_wallet && !ptr->postponed_main_worked_started)
{
- LOG_ERROR("Failed to start wallets_manager");
- return GENERAL_INTERNAL_ERRROR_INIT;
+ if (!ptr->gwm.start())
+ {
+ LOG_ERROR("Failed to start wallets_manager");
+ return GENERAL_INTERNAL_ERRROR_INIT;
+ }
+ ptr->postponed_main_worked_started = true;
}
LOG_PRINT_L0("[INIT PLAIN_WALLET_INSTANCE] Ver:" << PROJECT_VERSION_LONG << "(" << BUILD_TYPE << ")");
@@ -261,11 +280,12 @@ namespace plain_wallet
std::string init(const std::string& address, const std::string& working_dir, int log_level)
{
epee::net_utils::http::url_content url_data = AUTO_VAL_INIT(url_data);
- if(!epee::net_utils::parse_url(address, url_data))
+ if(!address.empty() && !epee::net_utils::parse_url(address, url_data))
{
LOG_ERROR("Failed to parse address");
return API_RETURN_CODE_BAD_ARG;
}
+
return init(url_data.host, std::to_string(url_data.port), working_dir, log_level);
}
@@ -438,7 +458,10 @@ namespace plain_wallet
{
ok_response.result.recovered = true;
}
- inst_ptr->gwm.run_wallet(ok_response.result.wallet_id);
+ if (!inst_ptr->postponed_run_wallet)
+ {
+ inst_ptr->gwm.run_wallet(ok_response.result.wallet_id);
+ }
return epee::serialization::store_t_to_json(ok_response);
}
@@ -460,7 +483,10 @@ namespace plain_wallet
{
ok_response.result.recovered = true;
}
- inst_ptr->gwm.run_wallet(ok_response.result.wallet_id);
+ if (!inst_ptr->postponed_run_wallet)
+ {
+ inst_ptr->gwm.run_wallet(ok_response.result.wallet_id);
+ }
return epee::serialization::store_t_to_json(ok_response);
}
error_response err_result = AUTO_VAL_INIT(err_result);
@@ -481,7 +507,10 @@ namespace plain_wallet
{
ok_response.result.recovered = true;
}
- inst_ptr->gwm.run_wallet(ok_response.result.wallet_id);
+ if (!inst_ptr->postponed_run_wallet)
+ {
+ inst_ptr->gwm.run_wallet(ok_response.result.wallet_id);
+ }
return epee::serialization::store_t_to_json(ok_response);
}
error_response err_result = AUTO_VAL_INIT(err_result);
@@ -550,6 +579,52 @@ namespace plain_wallet
return std::string("{ \"job_id\": ") + std::to_string(job_id) + "}";
}
+ std::string handle_reset_connection_url(const std::string& url)
+ {
+ GET_INSTANCE_PTR(inst_ptr);
+ inst_ptr->gwm.set_remote_node_url(url);
+
+ view::api_response ar = AUTO_VAL_INIT(ar);
+ ar.error_code = API_RETURN_CODE_OK;
+ return epee::serialization::store_t_to_json(ar);
+ }
+
+ std::string handle_run_wallet(uint64_t instance_id)
+ {
+ GET_INSTANCE_PTR(inst_ptr);
+
+
+ //postponed worker loop launch
+ if (!inst_ptr->postponed_main_worked_started)
+ {
+ if (!inst_ptr->gwm.start())
+ {
+ LOG_ERROR("Failed to start wallets_manager");
+ return API_RETURN_CODE_INTERNAL_ERROR;
+ }
+ inst_ptr->postponed_main_worked_started = true;
+ }
+
+ view::api_response ar = AUTO_VAL_INIT(ar);
+ ar.error_code = inst_ptr->gwm.run_wallet(instance_id);
+ return epee::serialization::store_t_to_json(ar);
+ }
+
+ std::string handle_configure(const std::string& settings_json)
+ {
+ GET_INSTANCE_PTR(inst_ptr);
+ configure_object conf = AUTO_VAL_INIT(conf);
+ configure_response conf_resp = AUTO_VAL_INIT(conf_resp);
+ bool res = epee::serialization::load_t_from_json(conf, settings_json);
+ if (!res)
+ {
+ conf_resp.status = API_RETURN_CODE_BAD_ARG;
+ return epee::serialization::store_t_to_json(conf_resp);
+ }
+ inst_ptr->postponed_run_wallet = conf.postponed_run_wallet;
+ conf_resp.status = API_RETURN_CODE_OK;
+ return epee::serialization::store_t_to_json(conf_resp);
+ }
std::string sync_call(const std::string& method_name, uint64_t instance_id, const std::string& params)
{
@@ -612,6 +687,18 @@ namespace plain_wallet
{
res = get_wallet_status(instance_id);
}
+ else if (method_name == "configure")
+ {
+ res = handle_configure(params);
+ }
+ else if (method_name == "reset_connection_url")
+ {
+ res = handle_reset_connection_url(params);
+ }
+ else if (method_name == "run_wallet")
+ {
+ res = handle_run_wallet(instance_id);
+ }
else
{
view::api_response ar = AUTO_VAL_INIT(ar);
@@ -621,9 +708,6 @@ namespace plain_wallet
return res;
}
-
-
-
std::string try_pull_result(uint64_t job_id)
{
auto inst_ptr = std::atomic_load(&ginstance_ptr);
diff --git a/src/wallet/plain_wallet_api_defs.h b/src/wallet/plain_wallet_api_defs.h
index 9273d524..613227d0 100644
--- a/src/wallet/plain_wallet_api_defs.h
+++ b/src/wallet/plain_wallet_api_defs.h
@@ -47,4 +47,19 @@ namespace plain_wallet
END_KV_SERIALIZE_MAP()
};
+ struct configure_object
+ {
+ bool postponed_run_wallet = false;
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(postponed_run_wallet)
+ END_KV_SERIALIZE_MAP()
+ };
+ struct configure_response
+ {
+ std::string status;
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(status)
+ END_KV_SERIALIZE_MAP()
+ };
+
} // namespace tools
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index f7078763..5ab899dd 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -38,7 +38,7 @@ using namespace epee;
#endif
#ifndef DISABLE_TOR
- #include "common/tor_helper.h"
+#include "common/tor_helper.h"
#endif
#include "storages/levin_abstract_invoke2.h"
@@ -69,7 +69,6 @@ namespace tools
{
wallet2::wallet2()
: m_stop(false)
- , m_wcallback(new i_wallet2_callback()) //stub
, m_core_proxy(new default_http_core_proxy())
, m_upper_transaction_size_limit(0)
, m_fake_outputs_count(0)
@@ -129,7 +128,7 @@ namespace tools
//----------------------------------------------------------------------------------------------------
std::string wallet2::transfer_flags_to_str(uint32_t flags)
{
- std::string result(7, ' ');
+ std::string result(8, ' ');
if (flags & WALLET_TRANSFER_DETAIL_FLAG_SPENT)
result[0] = 's';
if (flags & WALLET_TRANSFER_DETAIL_FLAG_BLOCKED)
@@ -142,8 +141,11 @@ std::string wallet2::transfer_flags_to_str(uint32_t flags)
result[4] = 'c';
if (flags & WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM)
result[5] = 'h';
+ if (flags & WALLET_TRANSFER_DETAIL_CONCISE_MODE_PRESERVE)
+ result[6] = 'p';
if (flags & WALLET_TRANSFER_DETAIL_FLAG_ASSET_OP_RESERVATION)
- result[6] = 'a';
+ result[7] = 'a';
+
return result;
}
//----------------------------------------------------------------------------------------------------
@@ -180,11 +182,11 @@ bool wallet2::set_core_proxy(const std::shared_ptr& proxy)
//----------------------------------------------------------------------------------------------------
void wallet2::set_defragmentation_tx_settings(bool enabled, uint64_t min_outs, uint64_t max_outs, uint64_t max_allowed_amount, size_t decoys_count)
{
- m_defragmentation_tx_enabled = enabled;
- m_min_utxo_count_for_defragmentation_tx = min_outs;
- m_max_utxo_count_for_defragmentation_tx = max_outs;
- m_max_allowed_output_amount_for_defragmentation_tx = max_allowed_amount;
- m_decoys_count_for_defragmentation_tx = decoys_count;
+ m_defragmentation_tx_enabled = enabled;
+ m_min_utxo_count_for_defragmentation_tx = min_outs;
+ m_max_utxo_count_for_defragmentation_tx = max_outs;
+ m_max_allowed_output_amount_for_defragmentation_tx = max_allowed_amount;
+ m_decoys_count_for_defragmentation_tx = decoys_count;
if (enabled)
{
WLT_LOG_L0("Defragmentation tx creation is enabled, settings: min outs: " << min_outs << ", max outs: " << max_outs << ", max amount: " << print_money_brief(max_allowed_amount) <<
@@ -208,26 +210,26 @@ bool wallet2::get_transfer_info_by_key_image(const crypto::key_image& ki, transf
{
return false;
}
- THROW_IF_FALSE_WALLET_EX(it->second < m_transfers.size(), error::wallet_internal_error, "wrong out in transaction: internal index");
- td = m_transfers[it->second];
+ //THROW_IF_FALSE_WALLET_EX(it->second < m_transfers.size(), error::wallet_internal_error, "wrong out in transaction: internal index");
+ td = m_transfers.at(it->second);
i = it->second;
return true;
}
//----------------------------------------------------------------------------------------------------
bool wallet2::get_transfer_info_by_index(size_t i, transfer_details& td)
{
- WLT_CHECK_AND_ASSERT_MES(i < m_transfers.size(), false, "wrong out in transaction: internal index, m_transfers.size()=" << m_transfers.size());
- td = m_transfers[i];
+ //WLT_CHECK_AND_ASSERT_MES(i < m_transfers.size(), false, "wrong out in transaction: internal index, m_transfers.size()=" << m_transfers.size());
+ td = m_transfers.at(i);
return true;
}
//----------------------------------------------------------------------------------------------------
size_t wallet2::scan_for_collisions(std::unordered_map >& key_images)
{
- size_t count = 0;
- for (size_t i = 0; i != m_transfers.size(); i++)
+ size_t count = 0;
+ for (const auto& tr : m_transfers)
{
- key_images[m_transfers[i].m_key_image].push_back(i);
- if (key_images[m_transfers[i].m_key_image].size() > 1)
+ key_images[tr.second.m_key_image].push_back(tr.first);
+ if (key_images[tr.second.m_key_image].size() > 1)
count++;
}
return count;
@@ -238,9 +240,9 @@ size_t wallet2::fix_collisions()
std::unordered_map > key_images;
scan_for_collisions(key_images);
size_t count = 0;
- for (auto &coll_entry : key_images)
+ for (auto& coll_entry : key_images)
{
- if(coll_entry.second.size()<2)
+ if (coll_entry.second.size() < 2)
continue;
currency::COMMAND_RPC_CHECK_KEYIMAGES::request req_ki = AUTO_VAL_INIT(req_ki);
@@ -252,10 +254,10 @@ size_t wallet2::fix_collisions()
THROW_IF_FALSE_WALLET_INT_ERR_EX(*rsp_ki.images_stat.begin() != 0, "unable to get spent key image info for keyimage: " << coll_entry.first << "keyimages [0]=0");
- for (auto it = coll_entry.second.begin(); it!= coll_entry.second.end(); it++)
+ for (auto it = coll_entry.second.begin(); it != coll_entry.second.end(); it++)
{
- m_transfers[*it].m_flags |= WALLET_TRANSFER_DETAIL_FLAG_SPENT;
- m_transfers[*it].m_spent_height = *rsp_ki.images_stat.begin();
+ m_transfers.at(*it).m_flags |= WALLET_TRANSFER_DETAIL_FLAG_SPENT;
+ m_transfers.at(*it).m_spent_height = *rsp_ki.images_stat.begin();
WLT_LOG_L0("Fixed collision for key image " << coll_entry.first << " transfer " << count);
count++;
}
@@ -271,13 +273,13 @@ size_t wallet2::scan_for_transaction_entries(const crypto::hash& tx_id, const cr
for (auto it = m_transfers.begin(); it != m_transfers.end(); it++)
{
- if (check_ki && it->m_key_image == ki)
+ if (check_ki && it->second.m_key_image == ki)
{
- details.push_back(*it);
+ details.push_back(it->second);
}
- if (check_tx_id && get_transaction_hash(it->m_ptx_wallet_info->m_tx) == tx_id)
+ if (check_tx_id && get_transaction_hash(it->second.m_ptx_wallet_info->m_tx) == tx_id)
{
- details.push_back(*it);
+ details.push_back(it->second);
}
}
return details.size();
@@ -394,8 +396,10 @@ const crypto::public_key& wallet2::out_get_pub_key(const currency::tx_out_v& out
//----------------------------------------------------------------------------------------------------
void wallet2::process_ado_in_new_transaction(const currency::asset_descriptor_operation& ado, process_transaction_context& ptc)
{
- auto print_ado_owner = [ado](std::ostream& o){
- ado.descriptor.owner_eth_pub_key.has_value() ? o << ado.descriptor.owner_eth_pub_key.value() << " (ETH)" : o << ado.descriptor.owner;
+ auto print_ado_owner = [ado](/*std::ostream& o*/) { // temporary reverted to boring std::string, until operator<<(std::ostream& o, invocable_t callee) is fixed for C++17/Android
+ std::stringstream o;
+ if (ado.opt_descriptor.has_value()) { ado.opt_descriptor->owner_eth_pub_key.has_value() ? o << ado.opt_descriptor->owner_eth_pub_key.value() << " (ETH)" : o << ado.opt_descriptor->owner; }
+ return o.str();
};
do
@@ -406,70 +410,77 @@ void wallet2::process_ado_in_new_transaction(const currency::asset_descriptor_op
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
{
+
+ WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(ado.opt_descriptor.has_value(), "ado. missing opt_descriptor value at ASSET_DESCRIPTOR_OPERATION_REGISTER");
// Add an asset to ownership list if either:
// 1) we're the owner of the asset;
// or
// 2) we spent native coins in the tx (i.e. we sent it) AND it registers an asset with third-party ownership.
- if (ado.descriptor.owner != m_account.get_public_address().spend_public_key &&
- (!ado.descriptor.owner_eth_pub_key.has_value() || !ptc.spent_own_native_inputs))
+ if (ado.opt_descriptor->owner != m_account.get_public_address().spend_public_key &&
+ (!ado.opt_descriptor->owner_eth_pub_key.has_value() || !ptc.spent_own_native_inputs))
break;
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(m_own_asset_descriptors.count(asset_id) == 0, "asset with asset_id " << asset_id << " has already been registered in the wallet as own asset");
wallet_own_asset_context& asset_context = m_own_asset_descriptors[asset_id];
- epee::misc_utils::cast_assign_a_to_b(ado.descriptor, asset_context);
+ epee::misc_utils::cast_assign_a_to_b(*ado.opt_descriptor, asset_context);
std::stringstream ss;
ss << "New Asset Registered:"
<< ENDL << "asset id: " << asset_id
- << ENDL << "Owner: " << print_ado_owner
+ << ENDL << "Owner: " << print_ado_owner()
<< ENDL << "Name: " << asset_context.full_name
<< ENDL << "Ticker: " << asset_context.ticker
<< ENDL << "Total Max Supply: " << print_asset_money(asset_context.total_max_supply, asset_context.decimal_point)
<< ENDL << "Current Supply: " << print_asset_money(asset_context.current_supply, asset_context.decimal_point)
<< ENDL << "Decimal Point: " << (int)asset_context.decimal_point;
-
+
add_rollback_event(ptc.height, asset_register_event{ asset_id });
WLT_LOG_MAGENTA(ss.str(), LOG_LEVEL_0);
- if (m_wcallback)
- m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str());
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_message(i_wallet2_callback::ms_yellow, ss.str());
}
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
{
- auto it = m_own_asset_descriptors.find(asset_id);
- if (it == m_own_asset_descriptors.end())
- break;
+ // do nothing on emit/burn
+ //
+ //
+ //auto it = m_own_asset_descriptors.find(asset_id);
+ //if (it == m_own_asset_descriptors.end())
+ // break;
//asset had been updated
- add_rollback_event(ptc.height, asset_update_event{ it->first, it->second });
- epee::misc_utils::cast_assign_a_to_b(ado.descriptor, it->second);
+ //add_rollback_event(ptc.height, asset_update_event{ it->first, it->second });
+ //epee::misc_utils::cast_assign_a_to_b(ado.opt_descriptor, it->second);
}
- else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE )
+ else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE)
{
+ WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(ado.opt_descriptor.has_value(), "ado. missing opt_descriptor value at ASSET_DESCRIPTOR_OPERATION_UPDATE");
+
auto it = m_own_asset_descriptors.find(asset_id);
if (it == m_own_asset_descriptors.end())
{
- if (ado.descriptor.owner == m_account.get_public_address().spend_public_key)
+ if (ado.opt_descriptor->owner == m_account.get_public_address().spend_public_key)
{
// ownership of the asset acquired
wallet_own_asset_context& asset_context = m_own_asset_descriptors[asset_id];
- epee::misc_utils::cast_assign_a_to_b(ado.descriptor, asset_context);
+ epee::misc_utils::cast_assign_a_to_b(*ado.opt_descriptor, asset_context);
std::stringstream ss;
ss << "Asset ownership acquired:"
<< ENDL << "asset id: " << asset_id
- << ENDL << "Name: " << ado.descriptor.full_name
- << ENDL << "Ticker: " << ado.descriptor.ticker
- << ENDL << "Total Max Supply: " << print_asset_money(ado.descriptor.total_max_supply, ado.descriptor.decimal_point)
- << ENDL << "Current Supply: " << print_asset_money(ado.descriptor.current_supply, ado.descriptor.decimal_point)
- << ENDL << "Decimal Point: " << (int)ado.descriptor.decimal_point;
+ << ENDL << "Name: " << ado.opt_descriptor->full_name
+ << ENDL << "Ticker: " << ado.opt_descriptor->ticker
+ << ENDL << "Total Max Supply: " << print_asset_money(ado.opt_descriptor->total_max_supply, ado.opt_descriptor->decimal_point)
+ << ENDL << "Current Supply: " << print_asset_money(ado.opt_descriptor->current_supply, ado.opt_descriptor->decimal_point)
+ << ENDL << "Decimal Point: " << (int)ado.opt_descriptor->decimal_point;
add_rollback_event(ptc.height, asset_register_event{ asset_id });
WLT_LOG_MAGENTA(ss.str(), LOG_LEVEL_0);
- if (m_wcallback)
- m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str());
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_message(i_wallet2_callback::ms_yellow, ss.str());
}
else
{
@@ -480,7 +491,7 @@ void wallet2::process_ado_in_new_transaction(const currency::asset_descriptor_op
else
{
// check our ownership status: we lost it if the asset has new non-null owner (null means a third-party ownership, and in such a case we retain it in the own list whatever happens)
- if (ado.descriptor.owner != null_pkey && ado.descriptor.owner != m_account.get_public_address().spend_public_key)
+ if (ado.opt_descriptor->owner != null_pkey && ado.opt_descriptor->owner != m_account.get_public_address().spend_public_key)
{
//ownership of the asset had been transfered
add_rollback_event(ptc.height, asset_unown_event{ it->first, it->second });
@@ -489,23 +500,23 @@ void wallet2::process_ado_in_new_transaction(const currency::asset_descriptor_op
std::stringstream ss;
ss << "Asset ownership lost:"
<< ENDL << "asset id: " << asset_id
- << ENDL << "New owner: " << print_ado_owner
- << ENDL << "Name: " << ado.descriptor.full_name
- << ENDL << "Ticker: " << ado.descriptor.ticker
- << ENDL << "Total Max Supply: " << print_asset_money(ado.descriptor.total_max_supply, ado.descriptor.decimal_point)
- << ENDL << "Current Supply: " << print_asset_money(ado.descriptor.current_supply, ado.descriptor.decimal_point)
- << ENDL << "Decimal Point: " << (int)ado.descriptor.decimal_point;
+ << ENDL << "New owner: " << print_ado_owner()
+ << ENDL << "Name: " << ado.opt_descriptor->full_name
+ << ENDL << "Ticker: " << ado.opt_descriptor->ticker
+ << ENDL << "Total Max Supply: " << print_asset_money(ado.opt_descriptor->total_max_supply, ado.opt_descriptor->decimal_point)
+ << ENDL << "Current Supply: " << print_asset_money(ado.opt_descriptor->current_supply, ado.opt_descriptor->decimal_point)
+ << ENDL << "Decimal Point: " << (int)ado.opt_descriptor->decimal_point;
add_rollback_event(ptc.height, asset_register_event{ asset_id });
WLT_LOG_MAGENTA(ss.str(), LOG_LEVEL_0);
- if (m_wcallback)
- m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str());
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_message(i_wallet2_callback::ms_yellow, ss.str());
}
else
{
//just an update of the asset
add_rollback_event(ptc.height, asset_update_event{ it->first, it->second });
- epee::misc_utils::cast_assign_a_to_b(ado.descriptor, it->second);
+ epee::misc_utils::cast_assign_a_to_b(*ado.opt_descriptor, it->second);
}
}
}
@@ -598,7 +609,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
}
}
- for(auto& in : tx.vin)
+ for (auto& in : tx.vin)
{
ptc.sub_i = 0;
VARIANT_SWITCH_BEGIN(in);
@@ -640,13 +651,13 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
auto it = m_active_htlcs.find(std::make_pair(in_htlc.amount, boost::get(in_htlc.key_offsets[0])));
if (it != m_active_htlcs.end())
{
- transfer_details& td = m_transfers[it->second];
+ transfer_details& td = m_transfers.at(it->second);
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_ptx_wallet_info->m_tx.vout.size() > td.m_internal_output_index, "Internal error: wrong td.m_internal_output_index: " << td.m_internal_output_index);
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type() == typeid(tx_out_bare), "Internal error: wrong output type: " << td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type().name());
const boost::typeindex::type_info& ti = boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]).target.type();
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(ti == typeid(txout_htlc), "Internal error: wrong type of output's target: " << ti.name());
//input spend active htlc
- m_transfers[it->second].m_spent_height = height;
+ m_transfers.at(it->second).m_spent_height = height;
transfer_details_extra_option_htlc_info& tdeohi = get_or_add_field_to_variant_vector(td.varian_options);
tdeohi.origin = in_htlc.hltc_origin;
tdeohi.redeem_tx_id = ptc.tx_hash();
@@ -687,7 +698,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
pwallet_info->m_block_timestamp = b.timestamp;
if (is_auditable())
- {
+ {
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(pglobal_indexes && pglobal_indexes->size() == tx.vout.size(), "wrong pglobal_indexes = " << pglobal_indexes << "");
}
std::vector outputs_index_local;
@@ -705,7 +716,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
pglobal_indexes = &outputs_index_local;
}
}
-
+
for (size_t i_in_outs = 0; i_in_outs != outs.size(); i_in_outs++)
{
const wallet_out_info& out = outs[i_in_outs];
@@ -713,10 +724,10 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(o < tx.vout.size(), "wrong out in transaction: internal index: " << o << ", tx.vout.size(): " << tx.vout.size());
{
const currency::tx_out_v& out_v = tx.vout[o];
- bool out_type_zc = out_is_zc(out_v);
- bool out_type_to_key = out_is_to_key(out_v);
- bool out_type_htlc = out_is_to_htlc(out_v);
- bool out_type_multisig = out_is_multisig(out_v);
+ bool out_type_zc = out_is_zc(out_v);
+ bool out_type_to_key = out_is_to_key(out_v);
+ bool out_type_htlc = out_is_to_htlc(out_v);
+ bool out_type_multisig = out_is_multisig(out_v);
if (out_type_zc || out_type_to_key || out_type_htlc)
{
@@ -771,8 +782,8 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
// However, we continue to omit outputs with duplicate key images since they could originate from the same source (albeit impractically).
// -- sowle
- WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->second < m_transfers.size(), "m_key_images entry has wrong m_transfers index, it->second: " << it->second << ", m_transfers.size(): " << m_transfers.size());
- const transfer_details& local_td = m_transfers[it->second];
+ //WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->second < m_transfers.size(), "m_key_images entry has wrong m_transfers index, it->second: " << it->second << ", m_transfers.size(): " << m_transfers.size());
+ const transfer_details& local_td = m_transfers.at(it->second);
std::stringstream ss;
ss << "tx " << ptc.tx_hash() << " @ block " << height << " has output #" << o << " with amount " << out.amount;
@@ -781,8 +792,8 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
ss << "and key image " << ki << " that has already been seen in output #" << local_td.m_internal_output_index << " in tx " << get_transaction_hash(local_td.m_ptx_wallet_info->m_tx)
<< " @ block " << local_td.m_spent_height << ". This output can't ever be spent and will be skipped.";
WLT_LOG_YELLOW(ss.str(), LOG_LEVEL_0);
- if (m_wcallback)
- m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str());
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_message(i_wallet2_callback::ms_yellow, ss.str());
//if (out.is_native_coin())
//{
//WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(sum_of_native_outs >= out.amount, "sum_of_native_outs: " << sum_of_native_outs << ", out.amount:" << out.amount);
@@ -803,8 +814,8 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
ss << " with amount " << print_money_brief(out.amount)
<< " is targeted to this auditable wallet and has INCORRECT mix_attr = " << (uint64_t)mix_attr << ". Output is IGNORED.";
WLT_LOG_YELLOW(ss.str(), LOG_LEVEL_0);
- if (m_wcallback)
- m_wcallback->on_message(i_wallet2_callback::ms_red, ss.str());
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_message(i_wallet2_callback::ms_red, ss.str());
//if (out.is_native_coin())
//{
//WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(sum_of_native_outs >= out.amount, "sum_of_native_outs: " << sum_of_native_outs << ", out.amount:" << out.amount);
@@ -813,10 +824,10 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
continue; // skip the output
}
- ptc.employed_entries.receive.push_back(wallet_public::employed_tx_entry{ o , out.amount , out.asset_id});
-
- m_transfers.push_back(boost::value_initialized());
- transfer_details& td = m_transfers.back();
+ ptc.employed_entries.receive.push_back(wallet_public::employed_tx_entry{ o , out.amount , out.asset_id });
+ uint64_t new_index = m_transfers.empty() ? 0 : (--m_transfers.end())->first+1;
+ auto rsp = m_transfers.insert(std::make_pair(new_index, boost::value_initialized()));
+ transfer_details& td = rsp.first->second;
td.m_ptx_wallet_info = pwallet_info;
td.m_internal_output_index = o;
td.m_key_image = ki;
@@ -843,18 +854,18 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
td.m_flags |= WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER;
}
}
-
+
if (out_type_zc)
{
td.m_zc_info_ptr.reset(new transfer_details_base::ZC_out_info(out.amount_blinding_mask, out.asset_id_blinding_mask, out.asset_id));
}
- size_t transfer_index = m_transfers.size() - 1;
+ size_t transfer_index = new_index;
if (out_type_htlc)
{
const currency::txout_htlc& hltc = out_get_htlc(out_v);
//mark this as spent
- td.m_flags |= WALLET_TRANSFER_DETAIL_FLAG_SPENT;
+ td.m_flags |= WALLET_TRANSFER_DETAIL_FLAG_SPENT|WALLET_TRANSFER_DETAIL_CONCISE_MODE_PRESERVE;
//create entry for htlc input
htlc_expiration_trigger het = AUTO_VAL_INIT(het);
het.is_wallet_owns_redeem = (out_key == hltc.pkey_redeem) ? true : false;
@@ -923,7 +934,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
}
else if (out_type_htlc)
{
- WLT_LOG_L0("Detected HTLC[" << (td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM ? "REDEEM" : "REFUND") << "], transfer #" << transfer_index << ", amount: " << print_money(td.amount()) << ", with tx: " << ptc.tx_hash() << ", at height " << height);
+ WLT_LOG_L0("Detected HTLC[" << (td.m_flags & WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM ? "REDEEM" : "REFUND") << "], transfer #" << transfer_index << ", amount: " << print_money(td.amount()) << ", with tx: " << ptc.tx_hash() << ", at height " << height);
}
}
else if (out_type_multisig)
@@ -944,7 +955,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
}
}
-
+
//do final calculations
bool has_in_transfers = false;
@@ -963,7 +974,9 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
//check if there are asset_registration that belong to this wallet
const asset_descriptor_operation* pado = get_type_in_variant_container(tx.extra);
- if (pado && (ptc.employed_entries.receive.size() || ptc.employed_entries.spent.size() || pado->descriptor.owner == m_account.get_public_address().spend_public_key))
+ if (pado && (ptc.employed_entries.receive.size() || ptc.employed_entries.spent.size() || (pado->opt_descriptor.has_value() && pado->opt_descriptor->owner == m_account.get_public_address().spend_public_key) ||
+ (pado->opt_asset_id.has_value() && m_own_asset_descriptors.count(pado->opt_asset_id.value()))
+ ))
{
//check if there are asset_registration that belong to this wallet
process_ado_in_new_transaction(*pado, ptc);
@@ -979,7 +992,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
if (ptc.sum_of_own_native_inputs)
{//this actually is transfer transaction, notify about spend
if (ptc.sum_of_own_native_inputs > sum_of_native_outs)
- {//usual transfer
+ {//usual transfer
handle_money_spent2(b, tx, ptc.sum_of_own_native_inputs - (sum_of_native_outs + get_tx_fee(tx)), ptc.mtd, recipients, remote_aliases);
}
else
@@ -1033,7 +1046,7 @@ void wallet2::prepare_wti_decrypted_attachments(wallet_public::wallet_transfer_i
account_public_address sender_address = AUTO_VAL_INIT(sender_address);
wti.show_sender = handle_2_alternative_types_in_variant_container(decrypted_att, [&](const tx_payer& p) { sender_address = p.acc_addr; return false; /* <- continue? */ });
if (wti.show_sender)
- if(!wti.remote_addresses.size())
+ if (!wti.remote_addresses.size())
wti.remote_addresses.push_back(currency::get_account_address_as_str(sender_address));
}
else
@@ -1049,7 +1062,7 @@ void wallet2::prepare_wti_decrypted_attachments(wallet_public::wallet_transfer_i
wti.remote_addresses.push_back(addr_str);
LOG_PRINT_YELLOW("prepare_wti_decrypted_attachments, income=false, rem. addr = " << addr_str, LOG_LEVEL_0);
return true; // continue iterating through the container
- });
+ });
}
}
@@ -1071,10 +1084,10 @@ void wallet2::resend_unconfirmed()
if (!req.txs_as_hex.size())
return;
-
+
bool r = m_core_proxy->call_COMMAND_RPC_FORCE_RELAY_RAW_TXS(req, res);
WLT_CHECK_AND_ASSERT_MES(r, void(), "wrong result at call_COMMAND_RPC_FORCE_RELAY_RAW_TXS");
- WLT_CHECK_AND_ASSERT_MES(res.status == API_RETURN_CODE_OK, void(), "wrong result at call_COMMAND_RPC_FORCE_RELAY_RAW_TXS: status != OK, status=" << res.status);
+ WLT_CHECK_AND_ASSERT_MES(res.status == API_RETURN_CODE_OK, void(), "wrong result at call_COMMAND_RPC_FORCE_RELAY_RAW_TXS: status != OK, status=" << res.status);
WLT_LOG_GREEN("Relayed " << req.txs_as_hex.size() << " txs", LOG_LEVEL_0);
}
@@ -1127,10 +1140,10 @@ void wallet2::accept_proposal(const crypto::hash& contract_id, uint64_t b_accept
//prepare templates to let buyer release or burn escrow
bc_services::escrow_relese_templates_body artb = AUTO_VAL_INIT(artb);
- build_escrow_release_templates(contract_id,
+ build_escrow_release_templates(contract_id,
left_for_fee_in_multisig,
artb.tx_normal_template,
- artb.tx_burn_template,
+ artb.tx_burn_template,
contr_it->second.private_detailes);
@@ -1200,7 +1213,7 @@ void wallet2::finish_contract(const crypto::hash& contract_id, const std::string
}
else
{
- THROW_IF_FALSE_WALLET_INT_ERR_EX(false, "Unknow release_type = " << release_type);
+ THROW_IF_FALSE_WALLET_INT_ERR_EX(false, "Unknow release_type = " << release_type);
}
bool is_input_fully_signed = false;
@@ -1243,7 +1256,7 @@ void wallet2::accept_cancel_contract(const crypto::hash& contract_id, currency::
send_transaction_to_network(tx);
TIME_MEASURE_FINISH_MS(timing3);
if (timing1 + timing2 + timing1 > 500)
- WLT_LOG_RED("[wallet2::accept_cancel_contract] LOW PERFORMANCE: " << timing1 << "," << timing2 << "," << timing1, LOG_LEVEL_0);
+ WLT_LOG_RED("[wallet2::accept_cancel_contract] LOW PERFORMANCE: " << timing1 << "," << timing2 << "," << timing1, LOG_LEVEL_0);
if (p_cancellation_acceptance_tx != nullptr)
*p_cancellation_acceptance_tx = tx;
@@ -1255,7 +1268,7 @@ void wallet2::request_cancel_contract(const crypto::hash& contract_id, uint64_t
THROW_IF_FALSE_WALLET_INT_ERR_EX(contr_it != m_contracts.end(), "Unknow contract id: " << contract_id);
THROW_IF_FALSE_WALLET_INT_ERR_EX(contr_it->second.is_a, "contr_it->second.is_a supposed to be true at request_cancel_contract");
- THROW_IF_FALSE_WALLET_INT_ERR_EX(contr_it->second.state == tools::wallet_public::escrow_contract_details_basic::contract_accepted
+ THROW_IF_FALSE_WALLET_INT_ERR_EX(contr_it->second.state == tools::wallet_public::escrow_contract_details_basic::contract_accepted
|| contr_it->second.state == tools::wallet_public::escrow_contract_details_basic::contract_cancel_proposal_sent,
"incorrect contract state at request_cancel_contract(): " << tools::wallet_public::get_escrow_contract_state_name(contr_it->second.state) << ", expected states: contract_accepted (" << tools::wallet_public::escrow_contract_details_basic::contract_accepted << "), " <<
"contract_cancel_proposal_sent (" << tools::wallet_public::escrow_contract_details_basic::contract_cancel_proposal_sent << ")");
@@ -1314,11 +1327,11 @@ void wallet2::scan_tx_to_key_inputs(std::vector& found_transfers, cons
{
if (in.type() == typeid(currency::txin_to_key))
{
-
+
auto it = m_key_images.find(boost::get(in).k_image);
if (it != m_key_images.end())
found_transfers.push_back(it->second);
- }
+ }
}
}
//-----------------------------------------------------------------------------------------------------
@@ -1326,7 +1339,7 @@ void wallet2::change_contract_state(wallet_public::escrow_contract_details_basic
{
WLT_LOG_YELLOW("escrow contract STATE CHANGE (" << (contract.is_a ? "A," : "B,") << contract_id << " via tx " << get_transaction_hash(wti.tx) << ", height: " << wti.height << ") : "
<< wallet_public::get_escrow_contract_state_name(contract.state) << " -> " << wallet_public::get_escrow_contract_state_name(new_state), LOG_LEVEL_1);
-
+
contract.state = new_state;
contract.height = wti.height; // update height of last state change
}
@@ -1335,7 +1348,7 @@ void wallet2::change_contract_state(wallet_public::escrow_contract_details_basic
{
WLT_LOG_YELLOW("escrow contract STATE CHANGE (" << (contract.is_a ? "A," : "B,") << contract_id << " " << reason << ") : "
<< wallet_public::get_escrow_contract_state_name(contract.state) << " -> " << wallet_public::get_escrow_contract_state_name(new_state), LOG_LEVEL_1);
-
+
contract.state = new_state;
}
//-----------------------------------------------------------------------------------------------------
@@ -1343,8 +1356,8 @@ void from_outs_to_received_items(const std::vector& o
{
for (const auto& item : outs)
{
- if(!out_is_multisig(tx.vout[item.index]))
- received.push_back(tools::payment_details_subtransfer{ item.asset_id, item.amount});
+ if (!out_is_multisig(tx.vout[item.index]))
+ received.push_back(tools::payment_details_subtransfer{ item.asset_id, item.amount });
}
}
//-----------------------------------------------------------------------------------------------------
@@ -1369,7 +1382,7 @@ bool wallet2::handle_proposal(wallet_public::wallet_transfer_info& wti, const bc
wti.contract.resize(1);
static_cast(wti.contract.back()) = ed;
wti.contract.back().contract_id = ms_id;
-
+
//correct fee in case if it "B", cz fee is paid by "A"
if (!ed.is_a)
wti.fee = 0;
@@ -1411,7 +1424,7 @@ bool wallet2::handle_release_contract(wallet_public::wallet_transfer_info& wti,
{
change_contract_state(it->second, wallet_public::escrow_contract_details_basic::contract_released_burned, ms_id, wti);
wallet_public::wallet_sub_transfer_info* subptr = nullptr;
- for (auto& s: wti.subtransfers)
+ for (auto& s : wti.subtransfers)
{
if (s.asset_id == currency::native_coin_asset_id)
subptr = &s;
@@ -1518,7 +1531,7 @@ bool wallet2::handle_cancel_proposal(wallet_public::wallet_transfer_info& wti, c
WLT_LOG_RED("handle_cancel_proposal for contract (" << (it->second.is_a ? "A," : "B,") << contract_id << " via tx " << get_transaction_hash(wti.tx) << ", height: " << wti.height << ") : " << ENDL <<
"incorrect state " << wallet_public::get_escrow_contract_state_name(it->second.state) << ", while 'contract_accepted' or 'contract_cancel_proposal_sent' was expected -- decline cancel proposal", LOG_LEVEL_1);
}
-
+
return false;
}
//-----------------------------------------------------------------------------------------------------
@@ -1555,9 +1568,9 @@ bool wallet2::process_contract_info(wallet_public::wallet_transfer_info& wti, co
}
else if (
- sa.instruction == BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_NORMAL ||
- sa.instruction == BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_CANCEL ||
- sa.instruction == BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_BURN
+ sa.instruction == BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_NORMAL ||
+ sa.instruction == BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_CANCEL ||
+ sa.instruction == BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_BURN
)
{
handle_release_contract(wti, sa.instruction);
@@ -1604,7 +1617,7 @@ void wallet2::prepare_wti(wallet_public::wallet_transfer_info& wti, const proces
//escrow, and decryption should be processed as income flag
//let's assume that the one who pays for tx fee is sender of tx
- bool decrypt_attachment_as_income = !(tx_process_context.total_balance_change.count(currency::native_coin_asset_id) && tx_process_context.total_balance_change.at(currency::native_coin_asset_id) < 0 );
+ bool decrypt_attachment_as_income = !(tx_process_context.total_balance_change.count(currency::native_coin_asset_id) && tx_process_context.total_balance_change.at(currency::native_coin_asset_id) < 0);
std::vector decrypted_att;
bool has_zero_input_as_spent = false;
for (const auto& item : tx_process_context.employed_entries.spent)
@@ -1615,13 +1628,13 @@ void wallet2::prepare_wti(wallet_public::wallet_transfer_info& wti, const proces
break;
}
}
-
+
if (wti.tx_type == GUI_TX_TYPE_ESCROW_TRANSFER && !has_zero_input_as_spent)
decrypt_attachment_as_income = true;
decrypt_payload_items(decrypt_attachment_as_income, wti.tx, m_account.get_keys(), decrypted_att);
- if ((is_watch_only() && !decrypt_attachment_as_income)|| (wti.height > 638000 && !have_type_in_variant_container(decrypted_att)))
+ if ((is_watch_only() && !decrypt_attachment_as_income) || (wti.height > 638000 && !have_type_in_variant_container(decrypted_att)))
{
remove_field_of_type_from_extra(decrypted_att);
remove_field_of_type_from_extra(decrypted_att);
@@ -1676,44 +1689,10 @@ void wallet2::rise_on_transfer2(const wallet_public::wallet_transfer_info& wti)
std::list balances;
uint64_t mined_balance = 0;
this->balance(balances, mined_balance);
- m_wcallback->on_transfer2(wti, balances, mined_balance);
- // second call for legacy callback handlers
- //m_wcallback->on_transfer2(wti, balances, mined_balance);
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_transfer2(wti, balances, mined_balance);
}
//----------------------------------------------------------------------------------------------------
-/*
-void wallet2::handle_money_spent2(const currency::block& b,
- const currency::transaction& in_tx,
- uint64_t amount,
- const money_transfer2_details& td,
- const std::vector& recipients,
- const std::vector& remote_aliases)
-{
- m_transfer_history.push_back(AUTO_VAL_INIT(wallet_public::wallet_transfer_info()));
- wallet_public::wallet_transfer_info& wti = m_transfer_history.back();
- wti.is_income = false;
-
- wti.remote_addresses = recipients;
- wti.remote_aliases = remote_aliases;
- prepare_wti(wti, get_block_height(b), get_block_datetime(b), in_tx, amount, td);
- WLT_LOG_L1("[MONEY SPENT]: " << epee::serialization::store_t_to_json(wti));
- rise_on_transfer2(wti);
-}
-//----------------------------------------------------------------------------------------------------
-void wallet2::handle_money_received2(const currency::block& b, const currency::transaction& tx, uint64_t amount, const money_transfer2_details& td)
-{
- //decrypt attachments
- m_transfer_history.push_back(AUTO_VAL_INIT(wallet_public::wallet_transfer_info()));
- wallet_public::wallet_transfer_info& wti = m_transfer_history.back();
- wti.is_income = true;
- // TODO @#@# this function is only able to handle native coins atm, consider changing -- sowle
- wti.asset_id = native_coin_asset_id;
- prepare_wti(wti, get_block_height(b), get_block_datetime(b), tx, amount, td);
- WLT_LOG_L1("[MONEY RECEIVED]: " << epee::serialization::store_t_to_json(wti));
- rise_on_transfer2(wti);
-}
-*/
- //----------------------------------------------------------------------------------------------------
void wallet2::load_wti_from_process_transaction_context(wallet_public::wallet_transfer_info& wti, const process_transaction_context& tx_process_context)
{
wti.remote_addresses = tx_process_context.recipients;
@@ -1780,7 +1759,7 @@ void wallet2::unprocess_htlc_triggers_on_block_removed(uint64_t height)
auto pair_of_it = m_htlcs.equal_range(height);
for (auto it = pair_of_it.first; it != pair_of_it.second; it++)
{
- auto& tr = m_transfers[it->second.transfer_index];
+ auto& tr = m_transfers.at(it->second.transfer_index);
//found contract that supposed to be re-activated and set to active
if (it->second.is_wallet_owns_redeem)
{
@@ -1805,7 +1784,7 @@ void wallet2::unprocess_htlc_triggers_on_block_removed(uint64_t height)
{
LOG_ERROR("Error at putting back htlc: already exist?");
it_active_htlc->second = it->second.transfer_index;
-
+
}
else
{
@@ -1841,7 +1820,7 @@ void wallet2::process_htlc_triggers_on_block_added(uint64_t height)
auto pair_of_it = m_htlcs.equal_range(height);
for (auto it = pair_of_it.first; it != pair_of_it.second; it++)
{
- auto& tr = m_transfers[it->second.transfer_index];
+ auto& tr = m_transfers.at(it->second.transfer_index);
//found contract that supposed to be deactivated and set to innactive
if (it->second.is_wallet_owns_redeem)
{
@@ -1855,8 +1834,8 @@ void wallet2::process_htlc_triggers_on_block_added(uint64_t height)
tr.m_flags &= ~(WALLET_TRANSFER_DETAIL_FLAG_SPENT); //reset spent flag
m_found_free_amounts.clear(); //reset free amounts cache
tr.m_spent_height = 0;
- }
-
+ }
+
//reset cache
m_found_free_amounts.clear();
@@ -1892,7 +1871,7 @@ void wallet2::process_new_blockchain_entry(const currency::block& b, const curre
!(height == m_minimum_height || get_blockchain_current_size() <= 1), error::wallet_internal_error,
"current_index=" + std::to_string(height) + ", get_blockchain_current_height()=" + std::to_string(get_blockchain_current_size()));
-
+
//optimization: seeking only for blocks that are not older then the wallet creation time plus 1 day. 1 day is for possible user incorrect time setup
@@ -1910,21 +1889,22 @@ void wallet2::process_new_blockchain_entry(const currency::block& b, const curre
TIME_MEASURE_START(txs_handle_time);
size_t count = 0;
- for(const auto& tx_entry: bche.txs_ptr)
+ for (const auto& tx_entry : bche.txs_ptr)
{
if (b.tx_hashes.size() < count || currency::get_transaction_hash(tx_entry->tx) != b.tx_hashes[count])
{
- LOG_ERROR("Found tx order fail in process_new_blockchain_entry: count=" << count
+ LOG_ERROR("Found tx order fail in process_new_blockchain_entry: count=" << count
<< ", b.tx_hashes.size() = " << b.tx_hashes.size() << ", tx real id: " << currency::get_transaction_hash(tx_entry->tx) << ", bl_id: " << bl_id);
}
process_new_transaction(tx_entry->tx, height, b, &(tx_entry->m_global_output_indexes));
count++;
}
TIME_MEASURE_FINISH(txs_handle_time);
- WLT_LOG_L3("Processed block: " << bl_id << ", height " << height << ", " << miner_tx_handle_time + txs_handle_time << "(" << miner_tx_handle_time << "/" << txs_handle_time <<")ms");
- }else
+ WLT_LOG_L3("Processed block: " << bl_id << ", height " << height << ", " << miner_tx_handle_time + txs_handle_time << "(" << miner_tx_handle_time << "/" << txs_handle_time << ")ms");
+ }
+ else
{
- WLT_LOG_L3( "Skipped block by timestamp, height: " << height << ", block time " << b.timestamp << ", account time " << m_account.get_createtime());
+ WLT_LOG_L3("Skipped block by timestamp, height: " << height << ", block time " << b.timestamp << ", account time " << m_account.get_createtime());
}
m_chain.push_new_block_id(bl_id, height); //m_blockchain.push_back(bl_id);
m_last_bc_timestamp = b.timestamp;
@@ -1933,7 +1913,8 @@ void wallet2::process_new_blockchain_entry(const currency::block& b, const curre
process_htlc_triggers_on_block_added(height);
- m_wcallback->on_new_block(height, b);
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_new_block(height, b);
}
//----------------------------------------------------------------------------------------------------
@@ -1974,7 +1955,7 @@ void wallet2::set_minimum_height(uint64_t h)
//----------------------------------------------------------------------------------------------------
uint64_t wallet2::get_wallet_minimum_height()
{
-
+
if (m_minimum_height != WALLET_MINIMUM_HEIGHT_UNSET_CONST)
return m_minimum_height;
@@ -1988,7 +1969,7 @@ uint64_t wallet2::get_wallet_minimum_height()
return res.h;
}
//----------------------------------------------------------------------------------------------------
-void wallet2::pull_blocks(size_t& blocks_added, std::atomic& stop)
+void wallet2::pull_blocks(size_t& blocks_added, std::atomic& stop, bool& full_reset_needed)
{
blocks_added = 0;
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::request req = AUTO_VAL_INIT(req);
@@ -2039,12 +2020,33 @@ void wallet2::pull_blocks(size_t& blocks_added, std::atomic& stop)
"wrong daemon response: m_start_height=" + std::to_string(res.start_height) +
" not less than local blockchain size=" + std::to_string(get_blockchain_current_size()));
- handle_pulled_blocks(blocks_added, stop, res);
+ try
+ {
+ handle_pulled_blocks(blocks_added, stop, res, full_reset_needed);
+ }
+ catch (const tools::error::wallet_error_resync_needed& /*v*/)
+ {
+ full_reset_needed = true;
+ m_full_resync_requested_at_h = get_blockchain_current_size() - blocks_added;
+ }
+
+ if (full_reset_needed)
+ {
+ //back up m_unconfirmed_txs
+ //back up std::unordered_map m_tx_keys;
+ unconfirmed_txs_container tmp_unconfirmed = m_unconfirmed_txs;
+ tx_secrete_keys_container tmp_secrete_keys = m_tx_keys;
+ crypto::hash genesis = m_chain.get_genesis();
+ reset_all();
+ m_chain.set_genesis(genesis);
+ m_unconfirmed_txs = tmp_unconfirmed;
+ m_tx_keys = tmp_secrete_keys;
+ }
}
//----------------------------------------------------------------------------------------------------
-void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop,
- currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& res)
+void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop,
+ currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& res, bool& wallet_reset_needed)
{
size_t current_index = res.start_height;
m_last_known_daemon_height = res.current_height;
@@ -2053,7 +2055,7 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop
{
const currency::block& genesis = res.blocks.front().block_ptr->bl;
THROW_IF_TRUE_WALLET_EX(get_block_height(genesis) != 0, error::wallet_internal_error, "first block expected to be genesis");
- WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(res.blocks.front().coinbase_ptr, "Unexpected empty coinbase");
+ WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(res.blocks.front().coinbase_ptr, "Unexpected empty coinbase");
process_genesis_if_needed(genesis, &(res.blocks.front().coinbase_ptr->m_global_output_indexes));
res.blocks.pop_front();
++current_index;
@@ -2061,7 +2063,7 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop
}
uint64_t last_matched_index = 0;
- for(const auto& bl_entry: res.blocks)
+ for (const auto& bl_entry : res.blocks)
{
if (stop)
break;
@@ -2092,14 +2094,14 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop
//regular block handling
//self check
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(been_matched_block,
- "internal error: been_matched_block == false on process_new_blockchain_entry, bl_id" << bl_id << "h=" << height
- << " (start_height=" + std::to_string(res.start_height) + ")");
+ "internal error: been_matched_block == false on process_new_blockchain_entry, bl_id" << bl_id << "h=" << height
+ << " (start_height=" + std::to_string(res.start_height) + ")");
process_new_blockchain_entry(bl, bl_entry, bl_id, current_index);
++blocks_added;
}
else
- {
+ {
//checking if we need reorganize (might be just first matched block)
bool block_found = false;
bool block_matched = false;
@@ -2127,7 +2129,13 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop
}
//TODO: take into account date of wallet creation
//reorganize
- detach_blockchain(last_matched_index+1);
+ if (m_concise_mode && m_chain.get_blockchain_current_size() - (last_matched_index) > m_wallet_concise_mode_max_reorg_blocks)
+ {
+ m_full_resync_requested_at_h = m_chain.get_blockchain_current_size() - (last_matched_index + 1);
+ wallet_reset_needed = true;
+ return;
+ }
+ detach_blockchain(last_matched_index + 1);
process_new_blockchain_entry(bl, bl_entry, bl_id, height);
++blocks_added;
}
@@ -2140,7 +2148,8 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop
uint64_t next_percent = (100 * (current_index - m_height_of_start_sync)) / (res.current_height - m_height_of_start_sync);
if (next_percent != m_last_sync_percent)
{
- m_wcallback->on_sync_progress(next_percent);
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_sync_progress(next_percent);
m_last_sync_percent = next_percent;
}
}
@@ -2160,7 +2169,7 @@ void wallet2::refresh()
refresh(blocks_fetched);
}
//----------------------------------------------------------------------------------------------------
-void wallet2::refresh(size_t & blocks_fetched)
+void wallet2::refresh(size_t& blocks_fetched)
{
bool received_money = false;
m_stop = false;
@@ -2178,7 +2187,7 @@ detail::split_strategy_id_t wallet2::get_current_split_strategy()
{
if (is_need_to_split_outputs())
return tools::detail::ssi_digit;
- else
+ else
return tools::detail::ssi_void;
}
//
@@ -2241,7 +2250,7 @@ bool wallet2::has_related_alias_entry_unconfirmed(const currency::transaction& t
if (tei.m_alias.m_alias.size())
{
//have some check address involved
- if (tei.m_alias.m_address.spend_public_key == m_account.get_keys().account_address.spend_public_key &&
+ if (tei.m_alias.m_address.spend_public_key == m_account.get_keys().account_address.spend_public_key &&
tei.m_alias.m_address.view_public_key == m_account.get_keys().account_address.view_public_key)
return true;
@@ -2280,9 +2289,10 @@ bool wallet2::get_bare_unspent_outputs_stats(std::vector> buo_ids; // tx hash -> Bare Unspent Outs list
- for(size_t tid = 0; tid != m_transfers.size(); ++tid)
+ for (const auto& tr : m_transfers)
{
- const auto& td = m_transfers[tid];
+ uint64_t tid = tr.first;
+ const auto& td = m_transfers.at(tid);
if (!td.is_zc() && td.is_spendable())
{
buo_ids[td.tx_hash()].push_back(tid);
@@ -2294,17 +2304,17 @@ bool wallet2::get_bare_unspent_outputs_stats(std::vector MAX_INPUTS_FOR_SIMPLE_TX_EURISTIC)
tids_grouped_by_txs.emplace_back();
- for(auto& tid : buo_el.second)
+ for (auto& tid : buo_el.second)
{
if (tids_grouped_by_txs.back().tids.size() >= MAX_INPUTS_FOR_SIMPLE_TX_EURISTIC)
tids_grouped_by_txs.emplace_back();
tids_grouped_by_txs.back().tids.push_back((uint64_t)tid);
- tids_grouped_by_txs.back().total_amount += m_transfers[tid].m_amount;
+ tids_grouped_by_txs.back().total_amount += m_transfers.at(tid).m_amount;
}
}
@@ -2313,21 +2323,22 @@ bool wallet2::get_bare_unspent_outputs_stats(std::vector usable_zc_outs_tids; // grouped by amount
bool usable_zc_outs_tids_precalculated = false;
- auto precalculate_usable_zc_outs_if_needed = [&](){
- if (usable_zc_outs_tids_precalculated)
- return;
- size_t decoys = is_auditable() ? 0 : m_core_runtime_config.hf4_minimum_mixins;
- for(size_t tid = 0; tid != m_transfers.size(); ++tid)
- {
- auto& td = m_transfers[tid];
- if (td.is_zc() && td.is_native_coin() && is_transfer_ready_to_go(td, decoys))
- usable_zc_outs_tids.insert(std::make_pair(td.m_amount, tid));
- }
- usable_zc_outs_tids_precalculated = true;
+ auto precalculate_usable_zc_outs_if_needed = [&]() {
+ if (usable_zc_outs_tids_precalculated)
+ return;
+ size_t decoys = is_auditable() ? 0 : m_core_runtime_config.hf4_minimum_mixins;
+ for (const auto& tr : m_transfers)
+ {
+ uint64_t tid = tr.first;
+ auto& td = m_transfers.at(tid);
+ if (td.is_zc() && td.is_native_coin() && is_transfer_ready_to_go(td, decoys))
+ usable_zc_outs_tids.insert(std::make_pair(td.m_amount, tid));
+ }
+ usable_zc_outs_tids_precalculated = true;
};
std::unordered_set used_zc_outs;
- for(auto it = tids_grouped_by_txs.begin(); it != tids_grouped_by_txs.end(); )
+ for (auto it = tids_grouped_by_txs.begin(); it != tids_grouped_by_txs.end(); )
{
auto& group = *it;
if (group.total_amount < TX_MINIMUM_FEE)
@@ -2337,7 +2348,7 @@ bool wallet2::get_bare_unspent_outputs_stats(std::vectorfirst >= min_required_amount, "jt->first=" << jt->first << ", min_required_amount=" << min_required_amount);
if (used_zc_outs.count(jt->second) == 0)
@@ -2377,7 +2388,7 @@ bool wallet2::sweep_bare_unspent_outputs(const currency::account_public_address&
bool send_to_network = true;
size_t batch_index = 0;
- for(const batch_of_bare_unspent_outs& group : tids_grouped_by_txs)
+ for (const batch_of_bare_unspent_outs& group : tids_grouped_by_txs)
{
currency::finalized_tx ftx{};
currency::finalize_tx_param ftp{};
@@ -2391,13 +2402,13 @@ bool wallet2::sweep_bare_unspent_outputs(const currency::account_public_address&
return false;
}
uint64_t fee = TX_DEFAULT_FEE;
- std::vector destinations{tx_destination_entry(group.total_amount + group.additional_tid_amount - fee, target_address)};
- assets_selection_context needed_money_map{std::make_pair(native_coin_asset_id, selection_for_amount{group.total_amount + group.additional_tid_amount, group.total_amount + group.additional_tid_amount})};
+ std::vector destinations{ tx_destination_entry(group.total_amount + group.additional_tid_amount - fee, target_address) };
+ assets_selection_context needed_money_map{ std::make_pair(native_coin_asset_id, selection_for_amount{group.total_amount + group.additional_tid_amount, group.total_amount + group.additional_tid_amount}) };
try
{
prepare_tx_destinations(needed_money_map, get_current_split_strategy(), tx_dust_policy{}, destinations, 0 /* tx_flags */, ftp.prepared_destinations);
}
- catch(...)
+ catch (...)
{
on_tx_sent(batch_index, transaction{}, 0, 0, false, "destinations for tx couldn't be prepared");
LOG_PRINT_L0("prepare_tx_destinations failed, batch_index = " << batch_index);
@@ -2410,13 +2421,13 @@ bool wallet2::sweep_bare_unspent_outputs(const currency::account_public_address&
finalize_transaction(ftp, ftx, send_to_network);
on_tx_sent(batch_index, ftx.tx, group.total_amount + group.additional_tid_amount, fee, true, std::string());
}
- catch(std::exception& e)
+ catch (std::exception& e)
{
clear_transfers_from_flag(ftp.selected_transfers, WALLET_TRANSFER_DETAIL_FLAG_SPENT, std::string("exception on sweep bare UTXO, tx: ") + epee::string_tools::pod_to_hex(get_transaction_hash(ftx.tx)));
on_tx_sent(batch_index, transaction{}, 0, 0, false, e.what());
return false;
}
-
+
++batch_index;
}
@@ -2431,13 +2442,13 @@ bool wallet2::sweep_bare_unspent_outputs(const currency::account_public_address&
total_fee_spent = 0;
total_bare_outs_sent = 0;
auto on_tx_sent_callback = [&](size_t batch_index, const currency::transaction& tx, uint64_t amount, uint64_t fee, bool sent_ok, const std::string& err) {
- if (sent_ok)
- {
- total_bare_outs_sent += count_type_in_variant_container(tx.vin);
- ++total_txs_sent;
- total_fee_spent += fee;
- total_amount_sent += amount;
- }
+ if (sent_ok)
+ {
+ total_bare_outs_sent += count_type_in_variant_container(tx.vin);
+ ++total_txs_sent;
+ total_fee_spent += fee;
+ total_amount_sent += amount;
+ }
};
return sweep_bare_unspent_outputs(target_address, tids_grouped_by_txs, on_tx_sent_callback);
@@ -2453,10 +2464,10 @@ uint64_t wallet2::get_directly_spent_transfer_index_by_input_in_tracking_wallet(
return get_directly_spent_transfer_index_by_input_in_tracking_wallet(0, inzc.key_offsets);
}
//----------------------------------------------------------------------------------------------------
-uint64_t wallet2::get_directly_spent_transfer_index_by_input_in_tracking_wallet(uint64_t amount, const std::vector & key_offsets)
+uint64_t wallet2::get_directly_spent_transfer_index_by_input_in_tracking_wallet(uint64_t amount, const std::vector& key_offsets)
{
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(is_auditable() && is_watch_only(), "this is not an auditable-watch-only (tracking) wallet");
-
+
uint64_t tid = UINT64_MAX;
// try to find a reference among own UTXOs
@@ -2470,8 +2481,8 @@ uint64_t wallet2::get_directly_spent_transfer_index_by_input_in_tracking_wallet(
if (it != m_amount_gindex_to_transfer_id.end())
{
tid = it->second;
- WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(tid < m_transfers.size(), "invalid tid: " << tid << ", ref from input with amount: " << amount << ", gindex: " << gindex);
- auto& td = m_transfers[it->second];
+ //WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(tid < m_transfers.size(), "invalid tid: " << tid << ", ref from input with amount: " << amount << ", gindex: " << gindex);
+ auto& td = m_transfers.at(it->second);
if (key_offsets.size() != 1)
{
// own output was used in non-direct transaction
@@ -2480,8 +2491,8 @@ uint64_t wallet2::get_directly_spent_transfer_index_by_input_in_tracking_wallet(
std::stringstream ss;
ss << "own transfer tid=" << tid << " tx=" << td.tx_hash() << " mix_attr=" << td.mix_attr() << ", is referenced by a transaction with mixins, ref from input with amount: " << amount << ", gindex: " << gindex;
WLT_LOG_YELLOW(ss.str(), LOG_LEVEL_0);
- if (m_wcallback)
- m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str());
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_message(i_wallet2_callback::ms_yellow, ss.str());
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.mix_attr() != CURRENCY_TO_KEY_OUT_FORCED_NO_MIX, ss.str()); // if mix_attr == 1 this should never happen (mixing in an output with mix_attr = 1) as the core must reject such txs
// our own output has mix_attr != 1 for some reason (a sender did not set correct mix_attr e.g.)
// but mixin count > 1 so we can't say it is spent for sure
@@ -2514,7 +2525,7 @@ void wallet2::handle_unconfirmed_tx(process_transaction_context& ptc)
//collect incomes
for (auto& o : outs)
{
- if(out_is_multisig(tx.vout[o.index]))
+ if (out_is_multisig(tx.vout[o.index]))
continue;
ptc.total_balance_change[o.asset_id] += o.amount;
@@ -2553,10 +2564,10 @@ void wallet2::handle_unconfirmed_tx(process_transaction_context& ptc)
{
// own output is being spent by this input
//sum_of_spent_native_coin += intk.amount;
- ptc.employed_entries.spent.push_back(wallet_public::employed_tx_entry{ i, m_transfers[tid].amount(), m_transfers[tid].get_asset_id() });
+ ptc.employed_entries.spent.push_back(wallet_public::employed_tx_entry{ i, m_transfers.at(tid).amount(), m_transfers.at(tid).get_asset_id() });
spend_transfers.push_back(tid);
- ptc.total_balance_change[currency::native_coin_asset_id] -= m_transfers[tid].amount();
- CHECK_AND_ASSERT_THROW_MES(m_transfers[tid].get_asset_id() == currency::native_coin_asset_id, "Unexpected asset id for native txin_to_key");
+ ptc.total_balance_change[currency::native_coin_asset_id] -= m_transfers.at(tid).amount();
+ CHECK_AND_ASSERT_THROW_MES(m_transfers.at(tid).get_asset_id() == currency::native_coin_asset_id, "Unexpected asset id for native txin_to_key");
}
}
else if (in.type() == typeid(currency::txin_zc_input))
@@ -2581,9 +2592,9 @@ void wallet2::handle_unconfirmed_tx(process_transaction_context& ptc)
if (tid != UINT64_MAX)
{
- ptc.employed_entries.spent.push_back(wallet_public::employed_tx_entry{ i, m_transfers[tid].amount(), m_transfers[tid].get_asset_id() });
+ ptc.employed_entries.spent.push_back(wallet_public::employed_tx_entry{ i, m_transfers.at(tid).amount(), m_transfers.at(tid).get_asset_id() });
spend_transfers.push_back(tid);
- ptc.total_balance_change[m_transfers[tid].get_asset_id()] -= m_transfers[tid].amount();
+ ptc.total_balance_change[m_transfers.at(tid).get_asset_id()] -= m_transfers.at(tid).amount();
}
}
else if (in.type() == typeid(currency::txin_multisig))
@@ -2641,14 +2652,14 @@ void wallet2::handle_unconfirmed_tx(process_transaction_context& ptc)
prepare_wti(unconfirmed_wti, ptc);
for (auto tr_index : spend_transfers)
{
- if (tr_index > m_transfers.size())
- {
- WLT_LOG_ERROR("INTERNAL ERROR: tr_index " << tr_index << " more then m_transfers.size()=" << m_transfers.size());
- continue;
- }
- uint32_t flags_before = m_transfers[tr_index].m_flags;
- m_transfers[tr_index].m_flags |= WALLET_TRANSFER_DETAIL_FLAG_SPENT;
- WLT_LOG_L1("wallet transfer #" << tr_index << " is marked as spent, flags: " << flags_before << " -> " << m_transfers[tr_index].m_flags << ", reason: UNCONFIRMED tx: " << ptc.tx_hash());
+ //if (tr_index > m_transfers.size())
+ //{
+ // WLT_LOG_ERROR("INTERNAL ERROR: tr_index " << tr_index << " more then m_transfers.size()=" << m_transfers.size());
+ // continue;
+ //}
+ uint32_t flags_before = m_transfers.at(tr_index).m_flags;
+ m_transfers.at(tr_index).m_flags |= WALLET_TRANSFER_DETAIL_FLAG_SPENT;
+ WLT_LOG_L1("wallet transfer #" << tr_index << " is marked as spent, flags: " << flags_before << " -> " << m_transfers.at(tr_index).m_flags << ", reason: UNCONFIRMED tx: " << ptc.tx_hash());
unconfirmed_wti.selected_indicies.push_back(tr_index);
}
rise_on_transfer2(unconfirmed_wti);
@@ -2667,13 +2678,13 @@ void wallet2::scan_tx_pool(bool& has_related_alias_in_unconfirmed)
if (!r)
throw error::no_connection_to_daemon(LOCATION_STR, "get_tx_pool");
THROW_IF_TRUE_WALLET_EX(res.status != API_RETURN_CODE_OK, error::get_blocks_error, res.status);
-
+
//- @#@ ----- debug
#ifdef _DEBUG
std::stringstream ss;
ss << "TXS FROM POOL: " << ENDL;
- for (const auto &tx_blob : res.txs)
+ for (const auto& tx_blob : res.txs)
{
currency::transaction tx;
bool r = parse_and_validate_tx_from_blob(tx_blob, tx);
@@ -2683,7 +2694,7 @@ void wallet2::scan_tx_pool(bool& has_related_alias_in_unconfirmed)
ss << tx_hash << ENDL;
}
ss << "UNCONFIRMED TXS: " << ENDL;
- for (const auto &tx_it : m_unconfirmed_in_transfers)
+ for (const auto& tx_it : m_unconfirmed_in_transfers)
{
ss << tx_it.first << ENDL;
}
@@ -2696,7 +2707,7 @@ void wallet2::scan_tx_pool(bool& has_related_alias_in_unconfirmed)
has_related_alias_in_unconfirmed = false;
uint64_t tx_expiration_ts_median = res.tx_expiration_ts_median; //get_tx_expiration_median();
- for (const auto &tx_blob : res.txs)
+ for (const auto& tx_blob : res.txs)
{
currency::transaction tx;
//money_transfer2_details td;
@@ -2724,8 +2735,8 @@ void wallet2::scan_tx_pool(bool& has_related_alias_in_unconfirmed)
// IF NOT EXISTS IN unconfirmed_multisig_transfers_in_tx_pool AND EXISTS IN m_unconfirmed_multisig_transfers => EITHER became confirmed (added to the blockchain) OR removed from the pool for some other reason (clear spent flag if there's spent height == 0, means wasn't added to the blockchain)
std::unordered_set unconfirmed_in_multisig_transfers;
- for(auto& el : m_unconfirmed_in_transfers)
- for(auto &in : el.second.vin)
+ for (auto& el : m_unconfirmed_in_transfers)
+ for (auto& in : el.second.vin)
if (in.type() == typeid(txin_multisig))
unconfirmed_in_multisig_transfers.insert(boost::get(in).multisig_out_id);
@@ -2739,7 +2750,7 @@ void wallet2::scan_tx_pool(bool& has_related_alias_in_unconfirmed)
// Process unconfirmed tx dissapeared from the pool
auto it = m_multisig_transfers.find(multisig_id);
- if (it != m_multisig_transfers.end() && it->second.m_flags&WALLET_TRANSFER_DETAIL_FLAG_SPENT)
+ if (it != m_multisig_transfers.end() && it->second.m_flags & WALLET_TRANSFER_DETAIL_FLAG_SPENT)
{
if (it->second.m_spent_height == 0)
{
@@ -2795,20 +2806,21 @@ bool wallet2::scan_not_compliant_unconfirmed_txs()
//lookup all used transfer and update flags
for (auto i : it->second.selected_indicies)
{
- if (i >= m_transfers.size())
+ //if (i >= m_transfers.size())
+ //{
+ // WLT_LOG_ERROR("Wrong index '" << i << "' in 'selected_indicies', while m_transfers.size() = " << m_transfers.size());
+ // continue;
+ //}
+ if (!m_transfers.at(i).m_spent_height)
{
- WLT_LOG_ERROR("Wrong index '" << i << "' in 'selected_indicies', while m_transfers.size() = " << m_transfers.size());
- continue;
- }
- if (!m_transfers[i].m_spent_height)
- {
- uint32_t flags_before = m_transfers[i].m_flags;
- m_transfers[i].m_flags &= ~(WALLET_TRANSFER_DETAIL_FLAG_SPENT); // TODO: consider removing other blocking flags (e.g. for escrow tx) -- sowle
- WLT_LOG_BLUE("mark transfer #" << i << " as unspent, flags: " << flags_before << " -> " << m_transfers[i].m_flags << ", reason: removing unconfirmed tx " << it->second.tx_hash, LOG_LEVEL_0);
+ uint32_t flags_before = m_transfers.at(i).m_flags;
+ m_transfers.at(i).m_flags &= ~(WALLET_TRANSFER_DETAIL_FLAG_SPENT); // TODO: consider removing other blocking flags (e.g. for escrow tx) -- sowle
+ WLT_LOG_BLUE("mark transfer #" << i << " as unspent, flags: " << flags_before << " -> " << m_transfers.at(i).m_flags << ", reason: removing unconfirmed tx " << it->second.tx_hash, LOG_LEVEL_0);
}
}
//fire some event
- m_wcallback->on_transfer_canceled(it->second);
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_transfer_canceled(it->second);
m_unconfirmed_txs.erase(it++);
}
else
@@ -2832,13 +2844,14 @@ bool wallet2::scan_not_compliant_unconfirmed_txs()
}
}
- size_t sz = m_transfers.size();
- for (size_t i = 0; i != sz; i++)
+
+ for (auto& tr : m_transfers)
{
- auto& t = m_transfers[i];
-
- if (t.m_flags&WALLET_TRANSFER_DETAIL_FLAG_SPENT && !t.m_spent_height && !static_cast(t.m_flags&WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION)
- && !t.is_htlc())
+ uint64_t i = tr.first;
+ auto& t = tr.second;
+
+ if (t.m_flags & WALLET_TRANSFER_DETAIL_FLAG_SPENT && !t.m_spent_height && !static_cast(t.m_flags & WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION)
+ && !t.is_htlc())
{
//check if there is unconfirmed for this transfer is no longer exist?
if (!ki_in_unconfirmed.count((t.m_key_image)))
@@ -2849,28 +2862,45 @@ bool wallet2::scan_not_compliant_unconfirmed_txs()
}
}
}
-
+
return true;
}
//----------------------------------------------------------------------------------------------------
-void wallet2::refresh(size_t & blocks_fetched, bool& received_money, std::atomic& stop)
+void wallet2::refresh(size_t& blocks_fetched, bool& received_money, std::atomic& stop)
{
load_whitelisted_tokens_if_not_loaded();
+ bool had_full_reset = false;
received_money = false;
blocks_fetched = 0;
size_t added_blocks = 0;
size_t try_count = 0;
- crypto::hash last_tx_hash_id = m_transfers.size() ? get_transaction_hash(m_transfers.back().m_ptx_wallet_info->m_tx) : null_hash;
+ size_t reset_count = 0;
+ crypto::hash last_tx_hash_id = m_transfers.size() ? get_transaction_hash((--m_transfers.end())->second.m_ptx_wallet_info->m_tx) : null_hash;
m_height_of_start_sync = get_blockchain_current_size();
m_last_sync_percent = 0;
while (!stop.load(std::memory_order_relaxed))
{
try
{
- pull_blocks(added_blocks, stop);
+ bool full_reset_needed = false;
+ pull_blocks(added_blocks, stop, full_reset_needed);
+ if (full_reset_needed)
+ {
+ if (reset_count > 1)
+ {
+ WLT_LOG_L0("Intenral error: reset_count infinit loop catch");
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_message(tools::i_wallet2_callback::ms_red, "Internal error: reset_count infinite loop catch");
+ return;
+ }
+ reset_count++;
+ m_height_of_start_sync = 0;
+ had_full_reset = true;
+ continue;
+ }
blocks_fetched += added_blocks;
- if(!added_blocks)
+ if (!added_blocks)
break;
}
catch (error::no_connection_to_daemon&)
@@ -2879,21 +2909,21 @@ void wallet2::refresh(size_t & blocks_fetched, bool& received_money, std::atomic
if (++try_count > 3)
return;
WLT_LOG_L2("no connection to the daemon, wait and try pull_blocks again (try_count: " << try_count << ", blocks_fetched: " << blocks_fetched << ")");
- if (m_wcallback)
- m_wcallback->on_message(tools::i_wallet2_callback::ms_red, "no connection to daemon");
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_message(tools::i_wallet2_callback::ms_red, "no connection to daemon");
std::this_thread::sleep_for(std::chrono::seconds(3));
}
catch (const std::exception& e)
{
blocks_fetched += added_blocks;
WLT_LOG_ERROR("refresh->pull_blocks failed, try_count: " << try_count << ", blocks_fetched: " << blocks_fetched << ", exception: " << e.what());
- if (m_wcallback)
- m_wcallback->on_message(tools::i_wallet2_callback::ms_red, std::string("error on pulling blocks: ") + e.what());
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_message(tools::i_wallet2_callback::ms_red, std::string("error on pulling blocks: ") + e.what());
return;
}
}
- if(last_tx_hash_id != (m_transfers.size() ? get_transaction_hash(m_transfers.back().m_ptx_wallet_info->m_tx) : null_hash))
+ if (last_tx_hash_id != (m_transfers.size() ? get_transaction_hash((--m_transfers.end())->second.m_ptx_wallet_info->m_tx) : null_hash))
received_money = true;
if (blocks_fetched)
@@ -2903,10 +2933,15 @@ void wallet2::refresh(size_t & blocks_fetched, bool& received_money, std::atomic
uint64_t tx_expiration_ts_median = get_tx_expiration_median();
handle_expiration_list(tx_expiration_ts_median);
handle_contract_expirations(tx_expiration_ts_median);
-
m_found_free_amounts.clear();
+ truncate_wallet();
}
-
+ if (had_full_reset)
+ {
+ blocks_fetched = get_blockchain_current_size() - m_full_resync_requested_at_h;
+ m_full_resync_requested_at_h = 0;
+ }
+
WLT_LOG("Refresh done, blocks received: " << blocks_fetched, blocks_fetched > 0 ? LOG_LEVEL_1 : LOG_LEVEL_2);
}
@@ -2919,7 +2954,7 @@ bool wallet2::handle_expiration_list(uint64_t tx_expiration_ts_median)
{
for (auto tr_ind : it->selected_transfers)
{
- auto &transfer = m_transfers[tr_ind];
+ auto& transfer = m_transfers.at(tr_ind);
if (!transfer.m_spent_height)
{
// Clear WALLET_TRANSFER_DETAIL_FLAG_BLOCKED and WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION flags only.
@@ -2927,7 +2962,7 @@ bool wallet2::handle_expiration_list(uint64_t tx_expiration_ts_median)
uint32_t flags_before = transfer.m_flags;
transfer.m_flags &= ~(WALLET_TRANSFER_DETAIL_FLAG_BLOCKED);
transfer.m_flags &= ~(WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION);
- WLT_LOG_GREEN("Unlocked money from expiration_list: transfer #" << tr_ind << ", flags: " << flags_before << " -> " << transfer.m_flags << ", amount: " << print_money(transfer.amount()) << ", tx: " <<
+ WLT_LOG_GREEN("Unlocked money from expiration_list: transfer #" << tr_ind << ", flags: " << flags_before << " -> " << transfer.m_flags << ", amount: " << print_money(transfer.amount()) << ", tx: " <<
(transfer.m_ptx_wallet_info != nullptr ? get_transaction_hash(transfer.m_ptx_wallet_info->m_tx) : null_hash), LOG_LEVEL_0);
}
@@ -2949,19 +2984,19 @@ void wallet2::handle_contract_expirations(uint64_t tx_expiration_ts_median)
{
switch (contract.second.state)
{
- case tools::wallet_public::escrow_contract_details_basic::contract_cancel_proposal_sent:
- if (is_tx_expired(contract.second.cancel_body.tx_cancel_template, tx_expiration_ts_median))
- change_contract_state(contract.second, tools::wallet_public::escrow_contract_details_basic::contract_accepted, contract.first, "cancel proposal expiration");
- break;
- case tools::wallet_public::escrow_contract_details_basic::contract_released_cancelled:
- if (contract.second.height == 0 && is_tx_expired(contract.second.cancel_body.tx_cancel_template, tx_expiration_ts_median))
- change_contract_state(contract.second, tools::wallet_public::escrow_contract_details_basic::contract_accepted, contract.first, "cancel acceptance expiration");
- break;
+ case tools::wallet_public::escrow_contract_details_basic::contract_cancel_proposal_sent:
+ if (is_tx_expired(contract.second.cancel_body.tx_cancel_template, tx_expiration_ts_median))
+ change_contract_state(contract.second, tools::wallet_public::escrow_contract_details_basic::contract_accepted, contract.first, "cancel proposal expiration");
+ break;
+ case tools::wallet_public::escrow_contract_details_basic::contract_released_cancelled:
+ if (contract.second.height == 0 && is_tx_expired(contract.second.cancel_body.tx_cancel_template, tx_expiration_ts_median))
+ change_contract_state(contract.second, tools::wallet_public::escrow_contract_details_basic::contract_accepted, contract.first, "cancel acceptance expiration");
+ break;
}
}
}
//----------------------------------------------------------------------------------------------------
-bool wallet2::refresh(size_t & blocks_fetched, bool& received_money, bool& ok, std::atomic& stop)
+bool wallet2::refresh(size_t& blocks_fetched, bool& received_money, bool& ok, std::atomic& stop)
{
try
{
@@ -3003,20 +3038,20 @@ void wallet2::detach_blockchain(uint64_t including_height)
// rollback incoming transfers from detaching subchain
{
- auto it = std::find_if(m_transfers.begin(), m_transfers.end(), [&](const transfer_details& td){return td.m_ptx_wallet_info->m_block_height >= including_height; });
- if (it != m_transfers.end())
+ auto it_start = std::find_if(m_transfers.begin(), m_transfers.end(), [&](const transfer_container::value_type& tr_e){return tr_e.second.m_ptx_wallet_info->m_block_height >= including_height; });
+ if (it_start != m_transfers.end())
{
- size_t i_start = it - m_transfers.begin();
- for (size_t i = i_start; i != m_transfers.size(); i++)
+ for (auto it = it_start; it!= m_transfers.end(); it++)
{
+ uint64_t i = it->first;
//check for htlc
- if (m_transfers[i].m_ptx_wallet_info->m_tx.vout[m_transfers[i].m_internal_output_index].type() == typeid(tx_out_bare) &&
- boost::get(m_transfers[i].m_ptx_wallet_info->m_tx.vout[m_transfers[i].m_internal_output_index]).target.type() == typeid(txout_htlc))
+ if (it->second.m_ptx_wallet_info->m_tx.vout[it->second.m_internal_output_index].type() == typeid(tx_out_bare) &&
+ boost::get(it->second.m_ptx_wallet_info->m_tx.vout[it->second.m_internal_output_index]).target.type() == typeid(txout_htlc))
{
//need to find an entry in m_htlc and remove it
- const txout_htlc& hltc = boost::get(boost::get(m_transfers[i].m_ptx_wallet_info->m_tx.vout[m_transfers[i].m_internal_output_index]).target);
- uint64_t expiration_height = m_transfers[i].m_ptx_wallet_info->m_block_height + hltc.expiration;
+ const txout_htlc& hltc = boost::get(boost::get(it->second.m_ptx_wallet_info->m_tx.vout[it->second.m_internal_output_index]).target);
+ uint64_t expiration_height = it->second.m_ptx_wallet_info->m_block_height + hltc.expiration;
auto pair_of_it = m_htlcs.equal_range(expiration_height);
bool found = false;
for (auto it = pair_of_it.first; it != pair_of_it.second; it++)
@@ -3032,20 +3067,20 @@ void wallet2::detach_blockchain(uint64_t including_height)
}
- if (!(m_transfers[i].m_key_image == null_ki && is_watch_only()))
+ if (!(it->second.m_key_image == null_ki && is_watch_only()))
{
- auto it_ki = m_key_images.find(m_transfers[i].m_key_image);
- WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it_ki != m_key_images.end(), "key image " << m_transfers[i].m_key_image << " not found");
- WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(m_transfers[i].m_ptx_wallet_info->m_block_height >= including_height, "transfer #" << i << " block height is less than " << including_height);
+ auto it_ki = m_key_images.find(it->second.m_key_image);
+ WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it_ki != m_key_images.end(), "key image " << it->second.m_key_image << " not found");
+ WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->second.m_ptx_wallet_info->m_block_height >= including_height, "transfer #" << i << " block height is less than " << including_height);
m_key_images.erase(it_ki);
}
remove_transfer_from_amount_gindex_map(i);
++transfers_detached;
}
- m_transfers.erase(it, m_transfers.end());
+ m_transfers.erase(it_start, m_transfers.end());
}
}
-
+
for (uint64_t i = get_top_block_height(); i != including_height - 1 && i != 0; i--)
{
unprocess_htlc_triggers_on_block_removed(i);
@@ -3055,9 +3090,10 @@ void wallet2::detach_blockchain(uint64_t including_height)
//rollback spends
// do not clear spent flag in spent transfers as corresponding txs are most likely in the pool
// they will be moved into m_unconfirmed_txs for clearing in future (if tx will expire of removed from pool)
- for (size_t i = 0, sz = m_transfers.size(); i < sz; ++i)
+ for (auto& tr_ : m_transfers)
{
- auto& tr = m_transfers[i];
+ uint64_t i = tr_.first;
+ auto& tr = tr_.second;
if (tr.m_spent_height >= including_height)
{
WLT_LOG_BLUE("Transfer [" << i << "] spent height: " << tr.m_spent_height << " -> 0, reason: detaching blockchain", LOG_LEVEL_1);
@@ -3074,7 +3110,7 @@ void wallet2::detach_blockchain(uint64_t including_height)
break;
tr_hist_it = it; // note that tr_hist_it->height >= height
}
-
+
if (tr_hist_it != m_transfer_history.rend())
{
auto it_from = --tr_hist_it.base();
@@ -3094,18 +3130,18 @@ void wallet2::detach_blockchain(uint64_t including_height)
}
m_transfer_history.erase(it_from, m_transfer_history.end());
}
-
+
//rollback payments
for (auto it = m_payments.begin(); it != m_payments.end(); )
{
- if(including_height <= it->second.m_block_height)
+ if (including_height <= it->second.m_block_height)
it = m_payments.erase(it);
else
++it;
}
//detach in m_last_zc_global_indexs
- while (m_last_zc_global_indexs.size() && including_height <= m_last_zc_global_indexs.begin()->first )
+ while (m_last_zc_global_indexs.size() && including_height <= m_last_zc_global_indexs.begin()->first)
{
m_last_zc_global_indexs.erase(m_last_zc_global_indexs.begin());
}
@@ -3300,7 +3336,7 @@ void wallet2::load_keys(const std::string& buff, const std::string& password, ui
const currency::account_keys& keys = m_account.get_keys();
r = epee::serialization::load_t_from_binary(m_account, account_data);
- r = r && verify_keys(keys.view_secret_key, keys.account_address.view_public_key);
+ r = r && verify_keys(keys.view_secret_key, keys.account_address.view_public_key);
if (keys.spend_secret_key == currency::null_skey)
m_watch_only = true;
else
@@ -3325,7 +3361,7 @@ void wallet2::assign_account(const currency::account_base& acc)
void wallet2::generate(const std::wstring& path, const std::string& pass, bool auditable_wallet)
{
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(validate_password(pass), "new wallet generation failed: password contains forbidden characters")
- clear();
+ clear();
prepare_file_names(path);
m_password = pass;
@@ -3347,7 +3383,7 @@ void wallet2::restore(const std::wstring& path, const std::string& pass, const s
clear();
prepare_file_names(path);
m_password = pass;
-
+
if (tracking_wallet)
{
r = m_account.restore_from_tracking_seed(seed_or_tracking_seed);
@@ -3439,8 +3475,8 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password)
WLT_LOG_L0("Unknown wallet body version(" << wbh.m_ver << "), resync initiated.");
need_to_resync = true;
}
-
-
+
+
if (m_watch_only && !is_auditable())
load_keys2ki(true, need_to_resync);
@@ -3448,13 +3484,13 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password)
boost::system::error_code ec = AUTO_VAL_INIT(ec);
m_current_wallet_file_size = boost::filesystem::file_size(wallet_, ec);
- WLT_LOG_L0("Loaded wallet file" << (m_watch_only ? " (WATCH ONLY) " : " ") << string_encoding::convert_to_ansii(m_wallet_file)
- << " with public address " << m_account.get_public_address_str()
+ WLT_LOG_L0("Loaded wallet file" << (m_watch_only ? " (WATCH ONLY) " : " ") << string_encoding::convert_to_ansii(m_wallet_file)
+ << " with public address " << m_account.get_public_address_str()
<< ", file_size: " << m_current_wallet_file_size
<< ", blockchain_size: " << m_chain.get_blockchain_current_size()
);
WLT_LOG_L1("[LOADING]Blockchain shortener state: " << ENDL << m_chain.get_internal_state_text());
-
+
load_votes_config();
WLT_LOG_L1("(after loading: pending_key_images: " << m_pending_key_images.size() << ", pki file elements: " << m_pending_key_images_file_container.size() << ", tx_keys: " << m_tx_keys.size() << ")");
@@ -3463,7 +3499,7 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password)
{
reset_history();
WLT_LOG_L0("Unable to load history data from wallet file, wallet will be resynced!");
- }
+ }
THROW_IF_TRUE_WALLET_EX(need_to_resync, error::wallet_load_notice_wallet_restored, epee::string_encoding::convert_to_ansii(m_wallet_file));
}
@@ -3532,7 +3568,7 @@ void wallet2::store(const std::wstring& path_to_save, const std::string& passwor
WLT_LOG_L1("[LOADING]Blockchain shortener state: " << ENDL << m_chain.get_internal_state_text());
// for the sake of safety perform a double-renaming: wallet file -> old tmp, new tmp -> wallet file, remove old tmp
-
+
boost::filesystem::path tmp_old_file_path = boost::filesystem::path(path_to_save);
tmp_old_file_path += L".oldtmp_" + std::to_wstring(ts);
@@ -3541,7 +3577,7 @@ void wallet2::store(const std::wstring& path_to_save, const std::string& passwor
boost::filesystem::rename(path_to_save, tmp_old_file_path);
WLT_LOG_L1("Renamed: " << ascii_path_to_save << " -> " << tmp_old_file_path.string());
}
-
+
boost::filesystem::rename(tmp_file_path, path_to_save);
WLT_LOG_L1("Renamed: " << tmp_file_path.string() << " -> " << ascii_path_to_save);
@@ -3550,10 +3586,10 @@ void wallet2::store(const std::wstring& path_to_save, const std::string& passwor
WLT_LOG_L1("Removed temporary file: " << tmp_old_file_path.string());
}
- bool path_to_save_exists = boost::filesystem::is_regular_file(path_to_save);
- bool tmp_file_path_exists = boost::filesystem::is_regular_file(tmp_file_path);
- bool tmp_old_file_path_exists = boost::filesystem::is_regular_file(tmp_old_file_path);
-
+ bool path_to_save_exists = boost::filesystem::is_regular_file(path_to_save);
+ bool tmp_file_path_exists = boost::filesystem::is_regular_file(tmp_file_path);
+ bool tmp_old_file_path_exists = boost::filesystem::is_regular_file(tmp_old_file_path);
+
boost::system::error_code ec = AUTO_VAL_INIT(ec);
m_current_wallet_file_size = boost::filesystem::file_size(path_to_save, ec);
if (path_to_save_exists && !tmp_file_path_exists && !tmp_old_file_path_exists)
@@ -3612,15 +3648,16 @@ void wallet2::store_watch_only(const std::wstring& path_to_save, const std::stri
bool stub = false;
wo.load_keys2ki(true, stub); // to create outkey2ki file
}
-
+
// populate pending key images for spent outputs (this will help to resync watch-only wallet)
- for (size_t ti = 0; ti < wo.m_transfers.size(); ++ti)
+ for (const auto& tr : m_transfers)
{
- const auto& td = wo.m_transfers[ti];
+
+ const auto& td = tr.second;
if (!td.is_spent())
continue; // only spent transfers really need to be stored, because watch-only wallet will not be able to figure out they were spent otherwise
- WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_internal_output_index < td.m_ptx_wallet_info->m_tx.vout.size(), "invalid transfer #" << ti);
- if(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type() != typeid(tx_out_bare))
+ WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_internal_output_index < td.m_ptx_wallet_info->m_tx.vout.size(), "invalid transfer #" << tr.first);
+ if (td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type() != typeid(tx_out_bare))
continue;
const currency::txout_target_v& out_t = boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]).target;
if (out_t.type() != typeid(currency::txout_to_key))
@@ -3694,9 +3731,11 @@ bool wallet2::balance(std::unordered_map subtransfers_by_assets_map;
- for(auto& utx : m_unconfirmed_txs)
+ for (auto& utx : m_unconfirmed_txs)
{
for (auto& subtransfer : utx.second.subtransfers)
{
@@ -3746,24 +3786,65 @@ bool wallet2::balance(std::unordered_mapsecond)) // if is_incoming == false, then we need to check for change and add it to total
{
- auto it_employed_entry = subtransfers_by_assets_map.find(emp_entry.asset_id);
- if (it_employed_entry == subtransfers_by_assets_map.end() || !(it_employed_entry->second)) // if is_incoming == false, then we need to check for change and add it to total
+ //it_employed_entry == subtransfers_by_assets_map.end() is a case when amount sent exactly equal amount received (someone producing more outputs for example)
+ //still need to add to total as it is a change
+ wallet_public::asset_balance_entry_base& e = balances[emp_entry.asset_id];
+ e.total += emp_entry.amount;
+ }
+ }
+ //}
+
+ }
+
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
+bool wallet2::truncate_wallet()
+{
+ if (m_concise_mode)
+ {
+ std::list items_to_remove;
+ for (auto& tr : m_transfers)
+ {
+ if (tr.second.is_spent() && tr.second.m_spent_height != 0 && !(tr.second.m_flags & WALLET_TRANSFER_DETAIL_CONCISE_MODE_PRESERVE) )
+ {
+ if (tr.second.m_spent_height + m_wallet_concise_mode_max_reorg_blocks < m_chain.get_top_block_height())
{
- //it_employed_entry == subtransfers_by_assets_map.end() is a case when amount sent exactly equal amount received (someone producing more outputs for example)
- //still need to add to total as it is a change
- wallet_public::asset_balance_entry_base& e = balances[emp_entry.asset_id];
- e.total += emp_entry.amount;
+ items_to_remove.push_back(tr.first);
}
}
- //}
-
+ }
+
+ return truncate_transfers_and_history(items_to_remove);
+ }
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
+bool wallet2::truncate_transfers_and_history(const std::list& items_to_remove)
+{
+ //delete from m_transfers
+ for (auto item : items_to_remove)
+ {
+ auto it = m_transfers.find(item);
+ WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it != m_transfers.end(),
+ "internal error: item to delet " << item << " not found");
+ m_transfers.erase(it);
+ }
+
+ //delete from recent_history
+ if (m_truncate_history_max_entries != 0 && m_transfer_history.size() > m_truncate_history_max_entries)
+ {
+ m_transfer_history.erase(m_transfer_history.begin(), m_transfer_history.end() - m_truncate_history_max_entries);
}
return true;
@@ -3786,9 +3867,9 @@ bool wallet2::balance(std::list& balances, u
}
asset_descriptor_base native_asset_info = AUTO_VAL_INIT(native_asset_info);
- native_asset_info.full_name = CURRENCY_NAME_SHORT_BASE;
- native_asset_info.ticker = CURRENCY_NAME_ABR;
- native_asset_info.decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT;
+ native_asset_info.full_name = CURRENCY_NAME_SHORT_BASE;
+ native_asset_info.ticker = CURRENCY_NAME_ABR;
+ native_asset_info.decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT;
custom_assets_local[currency::native_coin_asset_id] = native_asset_info;
for (const auto& item : balances_map)
@@ -3798,28 +3879,28 @@ bool wallet2::balance(std::list& balances, u
//check if it custom asset
auto it_cust = custom_assets_local.find(item.first);
- if(it_cust == custom_assets_local.end())
+ if (it_cust == custom_assets_local.end())
{
- if(!m_use_assets_whitelisting)
+ if (!m_use_assets_whitelisting)
continue;
auto it_local = m_whitelisted_assets.find(item.first);
- if(it_local == m_whitelisted_assets.end())
+ if (it_local == m_whitelisted_assets.end())
{
WLT_LOG_YELLOW("WARNING: unknown asset " << item.first << " found and skipped; it's NOT included in balance", LOG_LEVEL_1);
continue;
}
- else
+ else
{
asset_info = it_local->second;
}
}
- else
+ else
{
asset_info = it_cust->second;
custom_assets_local.erase(it_cust);
}
-
+
balances.push_back(wallet_public::asset_balance_entry());
wallet_public::asset_balance_entry& new_item = balances.back();
static_cast(new_item) = item.second;
@@ -3938,7 +4019,7 @@ bool wallet2::delete_custom_asset_id(const crypto::public_key& asset_id)
{
m_custom_assets.erase(it);
}
-
+
return true;
}
//----------------------------------------------------------------------------------------------------
@@ -3956,10 +4037,10 @@ const std::unordered_map& w
{
return m_own_asset_descriptors;
}
- //----------------------------------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------------
bool wallet2::load_whitelisted_tokens() const
{
- if(!m_use_assets_whitelisting)
+ if (!m_use_assets_whitelisting)
return true;
m_whitelisted_assets.clear();
@@ -4005,7 +4086,7 @@ bool wallet2::generate_utxo_defragmentation_transaction_if_needed(currency::tran
transfer(ctp, ftp, false, nullptr);
if (ftp.was_not_prepared)
- return false; // no such UTXO were found, not an error
+ return false; // no such UTXO were found, not an error
tx = ftp.tx;
return true;
@@ -4013,14 +4094,15 @@ bool wallet2::generate_utxo_defragmentation_transaction_if_needed(currency::tran
//----------------------------------------------------------------------------------------------------
std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool include_unspent /*= true*/, bool show_only_unknown /*= false*/, const std::string& filter_asset_ticker /*= std::string{}*/) const
{
- static const char* header = " index amount ticker g_index flags block tx out# asset id";
+ static const char* header = " index amount ticker g_index flags block tx out# asset id";
std::stringstream ss;
ss << header << ENDL;
size_t count = 0;
size_t unknown_assets_outs_count = 0;
- for (size_t i = 0; i != m_transfers.size(); ++i)
+ for (const auto& tr : m_transfers)
{
- const transfer_details& td = m_transfers[i];
+ uint64_t i = tr.first;
+ const transfer_details& td = tr.second;
if ((td.is_spent() && !include_spent) || (!td.is_spent() && !include_unspent))
continue;
@@ -4045,7 +4127,7 @@ std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool inclu
std::setw(6) << std::left << (native_coin ? std::string(" ") : adb.ticker) << " " << std::right <<
std::setw(7) << td.m_global_output_index << " " <<
std::setw(2) << std::setfill('0') << td.m_flags << std::setfill(' ') << ":" <<
- std::setw(7) << transfer_flags_to_str(td.m_flags) << " " <<
+ std::setw(8) << transfer_flags_to_str(td.m_flags) << " " <<
std::setw(7) << td.m_ptx_wallet_info->m_block_height << " " <<
get_transaction_hash(td.m_ptx_wallet_info->m_tx) << " " <<
std::setw(4) << td.m_internal_output_index << " ";
@@ -4053,7 +4135,7 @@ std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool inclu
ss << " ";
else
ss << td.get_asset_id();
-
+
ss << ENDL;
++count;
@@ -4083,7 +4165,7 @@ std::string wallet2::get_balance_str() const
uint64_t mined = 0;
balance(balances, mined);
- auto native_coin_it = std::find_if(balances.begin(), balances.end(), [&](auto& v){ return v.asset_info.asset_id == currency::native_coin_asset_id; });
+ auto native_coin_it = std::find_if(balances.begin(), balances.end(), [&](auto& v) { return v.asset_info.asset_id == currency::native_coin_asset_id; });
if (native_coin_it != balances.end())
{
balances.push_front(*native_coin_it);
@@ -4120,20 +4202,20 @@ std::string wallet2::get_balance_str_raw() const
static const char* header = " balance unlocked / [balance total] ticker asset id DP flags";
std::stringstream ss;
ss << header << ENDL;
-
+
uint64_t dummy = 0;
typedef std::unordered_map balances_map_t;
balances_map_t balances_map;
this->balance(balances_map, dummy);
- auto print_map = [&](const balances_map_t& map){
- for(const auto& entry : map)
+ auto print_map = [&](const balances_map_t& map) {
+ for (const auto& entry : map)
{
uint32_t asset_flags = 0;
asset_descriptor_base asset_info{};
bool has_info = get_asset_info(entry.first, asset_info, asset_flags);
ss << " " << std::left << std::setw(21) << print_fixed_decimal_point_with_trailing_spaces(entry.second.unlocked, asset_info.decimal_point);
- if(entry.second.total == entry.second.unlocked)
+ if (entry.second.total == entry.second.unlocked)
ss << std::string(21 + 3, ' ');
else
ss << " / " << std::setw(21) << print_fixed_decimal_point_with_trailing_spaces(entry.second.total, asset_info.decimal_point);
@@ -4162,7 +4244,7 @@ std::string wallet2::get_balance_str_raw() const
}
ss << ENDL;
}
- };
+ };
auto balances_map_it = balances_map.find(native_coin_asset_id);
if (balances_map_it != balances_map.end())
@@ -4178,23 +4260,23 @@ std::string wallet2::get_balance_str_raw() const
//print whitelist
ss << "WHITELIST: " << ENDL;
- for(const auto& entry : m_whitelisted_assets)
+ for (const auto& entry : m_whitelisted_assets)
{
- ss << " " << std::left << entry.first << " " << entry.second.ticker << ENDL;
+ ss << " " << std::left << entry.first << " " << entry.second.ticker << ENDL;
}
// print custom list
ss << "CUSTOM LIST: " << ENDL;
- for(const auto& entry : m_custom_assets)
+ for (const auto& entry : m_custom_assets)
{
ss << " " << std::left << entry.first << " " << entry.second.ticker << ENDL;
}
// print own list
ss << "OWN DESCRIPTORS LIST: " << ENDL;
-
- for(const auto& entry : m_own_asset_descriptors)
+
+ for (const auto& entry : m_own_asset_descriptors)
{
ss << " " << std::left << entry.first << " " << entry.second.ticker << ENDL;
}
@@ -4206,12 +4288,12 @@ void wallet2::get_payments(const std::string& payment_id, std::listset_connectivity(timeout, WALLET_RCP_COUNT_ATTEMNTS);
}
//----------------------------------------------------------------------------------------------------
-void wallet2::export_transaction_history(std::ostream& ss, const std::string& format, bool include_pos_transactions)
+void wallet2::export_transaction_history(std::ostream& ss, const std::string& format, bool include_pos_transactions)
{
//typedef int(*t_somefunc)(int, int);
typedef void(*playout_cb_type)(std::ostream&, const wallet_public::wallet_transfer_info&, size_t);
@@ -4601,7 +4683,7 @@ void wallet2::export_transaction_history(std::ostream& ss, const std::string& fo
wti.fee = currency::get_tx_fee(wti.tx);
cb(ss, wti, index);
return true;
- });
+ });
if (format == "json")
{
@@ -4636,7 +4718,7 @@ bool wallet2::is_transfer_okay_for_pos(const transfer_details& tr, bool is_zarca
//prevent staking of after-last-pow-coins
if (get_blockchain_current_size() - tr.m_ptx_wallet_info->m_block_height <= m_core_runtime_config.min_coinstake_age)
return false;
-
+
if (tr.m_ptx_wallet_info->m_block_height > m_last_pow_block_h)
return false;
@@ -4663,12 +4745,12 @@ size_t wallet2::get_pos_entries_count()
bool is_zarcanum_hf = is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM);
size_t counter = 0;
- for (size_t i = 0, size = m_transfers.size(); i < size; i++)
+ for (const auto& tr : m_transfers)
{
- auto& tr = m_transfers[i];
+ auto& td = tr.second;
uint64_t stake_unlock_time = 0;
- if (!is_transfer_okay_for_pos(tr, is_zarcanum_hf, stake_unlock_time))
+ if (!is_transfer_okay_for_pos(td, is_zarcanum_hf, stake_unlock_time))
continue;
++counter;
@@ -4680,9 +4762,10 @@ size_t wallet2::get_pos_entries_count()
bool wallet2::get_pos_entries(std::vector& entries)
{
bool is_zarcanum_hf = is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM);
- for (size_t i = 0; i != m_transfers.size(); i++)
+ for (const auto& td : m_transfers)
{
- auto& tr = m_transfers[i];
+ uint64_t i = td.first;
+ auto& tr = td.second;
uint64_t stake_unlock_time = 0;
if (!is_transfer_okay_for_pos(tr, is_zarcanum_hf, stake_unlock_time))
@@ -4714,8 +4797,8 @@ bool wallet2::proxy_to_daemon(const std::string& uri, const std::string& body, i
bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t full_block_reward, const currency::pos_entry& pe, currency::tx_generation_context& miner_tx_tgc, currency::block& b) const
{
bool r = false;
- WLT_CHECK_AND_ASSERT_MES(pe.wallet_index < m_transfers.size(), false, "invalid pe.wallet_index: " << pe.wallet_index);
- const transfer_details& td = m_transfers[pe.wallet_index];
+ //WLT_CHECK_AND_ASSERT_MES(pe.wallet_index < m_transfers.size(), false, "invalid pe.wallet_index: " << pe.wallet_index);
+ const transfer_details& td = m_transfers.at(pe.wallet_index);
const transaction& source_tx = td.m_ptx_wallet_info->m_tx;
const crypto::public_key source_tx_pub_key = get_tx_pub_key_from_extra(source_tx);
WLT_CHECK_AND_ASSERT_MES(pe.tx_out_index < source_tx.vout.size(), false, "invalid pe.tx_out_index: " << pe.tx_out_index);
@@ -4737,11 +4820,11 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
WLT_CHECK_AND_ASSERT_MES(stake_out_v.type() == typeid(tx_out_bare), false, "unexpected stake output type: " << stake_out_v.type().name() << ", expected: tx_out_bare");
const tx_out_bare& stake_out = boost::get(stake_out_v);
WLT_CHECK_AND_ASSERT_MES(stake_out.target.type() == typeid(txout_to_key), false, "unexpected stake output target type: " << stake_out.target.type().name() << ", expected: txout_to_key");
-
+
NLSAG_sig& sig = boost::get(b.miner_tx.signatures[0]);
txin_to_key& stake_input = boost::get(b.miner_tx.vin[1]);
const txout_to_key& stake_out_target = boost::get(stake_out.target);
-
+
// partially fill stake input
stake_input.k_image = pe.keyimage;
stake_input.amount = pe.amount;
@@ -4764,7 +4847,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
THROW_IF_FALSE_WALLET_EX(decoys_resp.status != API_RETURN_CODE_BUSY, error::daemon_busy, "getrandom_outs1.bin");
THROW_IF_FALSE_WALLET_EX(decoys_resp.status == API_RETURN_CODE_OK, error::get_random_outs_error, decoys_resp.status);
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(decoys_resp.outs.size() == 1, "got wrong number of decoys batches: " << decoys_resp.outs.size());
-
+
// we expect that less decoys can be returned than requested, we will use them all anyway
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(decoys_resp.outs[0].outs.size() <= m_required_decoys_count + 1, "for PoS stake tx got greater decoys to mix than requested: " << decoys_resp.outs[0].outs.size() << " < " << m_required_decoys_count + 1);
@@ -4773,7 +4856,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
std::unordered_set used_gindices;
size_t good_outs_count = 0;
- for(auto it = ring_candidates.begin(); it != ring_candidates.end(); )
+ for (auto it = ring_candidates.begin(); it != ring_candidates.end(); )
{
if (used_gindices.count(it->global_amount_index) != 0)
{
@@ -4788,15 +4871,15 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
}
++it;
}
-
+
// won't assert that ring_candidates.size() == m_required_decoys_count + 1 here as we will use all the decoys anyway
if (ring_candidates.size() < m_required_decoys_count + 1)
LOG_PRINT_YELLOW("PoS: using " << ring_candidates.size() - 1 << " decoys for mining tx, while " << m_required_decoys_count << " are required", LOG_LEVEL_1);
- ring_candidates.sort([](auto& l, auto& r){ return l.global_amount_index < r.global_amount_index; }); // sort them now (note absolute_sorted_output_offsets_to_relative_in_place() below)
+ ring_candidates.sort([](auto& l, auto& r) { return l.global_amount_index < r.global_amount_index; }); // sort them now (note absolute_sorted_output_offsets_to_relative_in_place() below)
uint64_t i = 0;
- for(auto& el : ring_candidates)
+ for (auto& el : ring_candidates)
{
uint64_t gindex = el.global_amount_index;
if (gindex == td.m_global_output_index)
@@ -4829,10 +4912,10 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
" block hash: " << block_hash << ENDL <<
" key image: " << stake_input.k_image << ENDL <<
" ring:" << ENDL;
- for(auto el: ring)
+ for (auto el : ring)
ss << " " << *el << ENDL;
ss << " signature:" << ENDL;
- for(auto el: sig.s)
+ for (auto el : sig.s)
ss << " " << el << ENDL;
WLT_LOG_L4(ss.str());
}
@@ -4881,7 +4964,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
std::unordered_set used_gindices;
size_t good_outs_count = 0;
- for(auto it = decoys.begin(); it != decoys.end(); )
+ for (auto it = decoys.begin(); it != decoys.end(); )
{
if (used_gindices.count(it->global_amount_index) != 0)
{
@@ -4898,10 +4981,10 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
}
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(decoys.size() == required_decoys_count + 1, "for PoS stake got less good decoys than required: " << decoys.size() << " < " << required_decoys_count);
- decoys.sort([](auto& l, auto& r){ return l.global_amount_index < r.global_amount_index; }); // sort them now (note absolute_sorted_output_offsets_to_relative_in_place() below)
+ decoys.sort([](auto& l, auto& r) { return l.global_amount_index < r.global_amount_index; }); // sort them now (note absolute_sorted_output_offsets_to_relative_in_place() below)
uint64_t i = 0;
- for(auto& el : decoys)
+ for (auto& el : decoys)
{
uint64_t gindex = el.global_amount_index;
if (gindex == td.m_global_output_index)
@@ -4921,7 +5004,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
}
stake_input.k_image = pe.keyimage;
- crypto::point_t stake_out_blinded_asset_id_pt = currency::native_coin_asset_id_pt + td.m_zc_info_ptr->asset_id_blinding_mask * crypto::c_point_X;
+ crypto::point_t stake_out_blinded_asset_id_pt = currency::native_coin_asset_id_pt + td.m_zc_info_ptr->asset_id_blinding_mask * crypto::c_point_X;
#ifndef NDEBUG
{
crypto::point_t source_amount_commitment = crypto::c_scalar_1div8 * td.m_amount * stake_out_blinded_asset_id_pt + crypto::c_scalar_1div8 * td.m_zc_info_ptr->amount_blinding_mask * crypto::c_point_G;
@@ -4929,7 +5012,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
WLT_CHECK_AND_ASSERT_MES(ring[secret_index].amount_commitment == stake_out.amount_commitment, false, "ring secret member doesn't match with the stake output");
WLT_CHECK_AND_ASSERT_MES(cxt.stake_amount == td.m_amount, false, "stake_amount missmatch");
}
- #endif
+#endif
crypto::hash hash_for_zarcanum_sig = get_block_hash(b);
@@ -4945,7 +5028,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
uint8_t err = 0;
r = crypto::zarcanum_generate_proof(hash_for_zarcanum_sig, cxt.kernel_hash, ring, cxt.last_pow_block_id_hashed, cxt.sk.kimage,
- secret_x, cxt.secret_q, secret_index, cxt.stake_amount, td.m_zc_info_ptr->asset_id_blinding_mask, cxt.stake_out_amount_blinding_mask, pseudo_out_amount_blinding_mask,
+ secret_x, cxt.secret_q, secret_index, cxt.stake_amount, td.m_zc_info_ptr->asset_id_blinding_mask, cxt.stake_out_amount_blinding_mask, pseudo_out_amount_blinding_mask,
static_cast(sig), &err);
WLT_CHECK_AND_ASSERT_MES(r, false, "zarcanum_generate_proof failed, err: " << (int)err);
@@ -4956,7 +5039,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
crypto::hash miner_tx_id = get_transaction_hash(b.miner_tx);
// proofs for miner_tx
-
+
// asset surjection proof
currency::zc_asset_surjection_proof asp{};
r = generate_asset_surjection_proof(miner_tx_id, false, miner_tx_tgc, asp); // has_non_zc_inputs == false because after the HF4 PoS mining is only allowed for ZC stakes inputs
@@ -4965,7 +5048,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful
// range proofs
currency::zc_outs_range_proof range_proofs{};
- r = generate_zc_outs_range_proof(miner_tx_id, 0, miner_tx_tgc, b.miner_tx.vout, range_proofs);
+ r = generate_zc_outs_range_proof(miner_tx_id, miner_tx_tgc, b.miner_tx.vout, range_proofs);
WLT_CHECK_AND_ASSERT_MES(r, false, "Failed to generate zc_outs_range_proof()");
b.miner_tx.proofs.emplace_back(std::move(range_proofs));
@@ -4994,10 +5077,10 @@ bool wallet2::fill_mining_context(mining_context& ctx)
ctx = mining_context{};
ctx.init(wide_difficulty_type(pos_details_resp.pos_basic_difficulty), pos_details_resp.sm, is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM));
- ctx.last_block_hash = pos_details_resp.last_block_hash;
- ctx.is_pos_allowed = pos_details_resp.pos_mining_allowed;
+ ctx.last_block_hash = pos_details_resp.last_block_hash;
+ ctx.is_pos_allowed = pos_details_resp.pos_mining_allowed;
ctx.is_pos_sequence_factor_good = pos_details_resp.pos_sequence_factor_is_good;
- ctx.starter_timestamp = pos_details_resp.starter_timestamp;
+ ctx.starter_timestamp = pos_details_resp.starter_timestamp;
ctx.status = API_RETURN_CODE_NOT_FOUND;
return true;
}
@@ -5013,7 +5096,7 @@ bool wallet2::try_mint_pos(const currency::account_public_address& miner_address
mining_context ctx = AUTO_VAL_INIT(ctx);
WLT_LOG_L2("Starting PoS mining iteration");
fill_mining_context(ctx);
-
+
if (!ctx.is_pos_allowed)
{
WLT_LOG_YELLOW("POS MINING NOT ALLOWED YET", LOG_LEVEL_0);
@@ -5027,7 +5110,7 @@ bool wallet2::try_mint_pos(const currency::account_public_address& miner_address
}
std::atomic stop(false);
- scan_pos(ctx, stop, [this](){
+ scan_pos(ctx, stop, [this]() {
size_t blocks_fetched;
refresh(blocks_fetched);
if (blocks_fetched)
@@ -5036,8 +5119,8 @@ bool wallet2::try_mint_pos(const currency::account_public_address& miner_address
return false;
}
return true;
- }, m_core_runtime_config);
-
+ }, m_core_runtime_config);
+
bool res = true;
if (ctx.status == API_RETURN_CODE_OK)
{
@@ -5050,10 +5133,10 @@ bool wallet2::try_mint_pos(const currency::account_public_address& miner_address
return res;
}
//------------------------------------------------------------------
-void wallet2::do_pos_mining_prepare_entry(mining_context& context, size_t transfer_index)
+void wallet2::do_pos_mining_prepare_entry(mining_context& context, const transfer_details& td)
{
- CHECK_AND_ASSERT_MES_NO_RET(transfer_index < m_transfers.size(), "transfer_index is out of bounds: " << transfer_index);
- const transfer_details& td = m_transfers[transfer_index];
+ //CHECK_AND_ASSERT_MES_NO_RET(transfer_index < m_transfers.size(), "transfer_index is out of bounds: " << transfer_index);
+ //const transfer_details& td = m_transfers.at(transfer_index);
crypto::scalar_t amount_blinding_mask{};
if (td.is_zc())
@@ -5063,7 +5146,7 @@ void wallet2::do_pos_mining_prepare_entry(mining_context& context, size_t transf
amount_blinding_mask, m_account.get_keys().view_secret_key);
}
//------------------------------------------------------------------
-bool wallet2::do_pos_mining_iteration(mining_context& context, size_t transfer_index, uint64_t ts)
+bool wallet2::do_pos_mining_iteration(mining_context& context, uint64_t ts)
{
return context.do_iteration(ts);
}
@@ -5114,8 +5197,8 @@ bool wallet2::build_minted_block(const mining_context& cxt, const currency::acco
//found a block, construct it, sign and push to daemon
WLT_LOG_GREEN("Found kernel, constructing block", LOG_LEVEL_0);
- WLT_CHECK_AND_ASSERT_MES(cxt.index < m_transfers.size(), false, "cxt.index = " << cxt.index << " is out of bounds");
- const transfer_details& td = m_transfers[cxt.index];
+ //WLT_CHECK_AND_ASSERT_MES(cxt.index < m_transfers.size(), false, "cxt.index = " << cxt.index << " is out of bounds");
+ const transfer_details& td = m_transfers.at(cxt.index);
currency::COMMAND_RPC_GETBLOCKTEMPLATE::request tmpl_req = AUTO_VAL_INIT(tmpl_req);
currency::COMMAND_RPC_GETBLOCKTEMPLATE::response tmpl_rsp = AUTO_VAL_INIT(tmpl_rsp);
@@ -5125,23 +5208,23 @@ bool wallet2::build_minted_block(const mining_context& cxt, const currency::acco
tmpl_req.extra_text = get_extra_text_for_block(m_chain.get_top_block_height());
tmpl_req.pe = AUTO_VAL_INIT(tmpl_req.pe);
- tmpl_req.pe.amount = td.amount();
- tmpl_req.pe.block_timestamp = td.m_ptx_wallet_info->m_block_timestamp;
- tmpl_req.pe.g_index = td.m_global_output_index;
- tmpl_req.pe.keyimage = td.m_key_image;
- tmpl_req.pe.stake_unlock_time = cxt.stake_unlock_time;
- tmpl_req.pe.tx_id = td.tx_hash();
- tmpl_req.pe.tx_out_index = td.m_internal_output_index;
- tmpl_req.pe.wallet_index = cxt.index;
+ tmpl_req.pe.amount = td.amount();
+ tmpl_req.pe.block_timestamp = td.m_ptx_wallet_info->m_block_timestamp;
+ tmpl_req.pe.g_index = td.m_global_output_index;
+ tmpl_req.pe.keyimage = td.m_key_image;
+ tmpl_req.pe.stake_unlock_time = cxt.stake_unlock_time;
+ tmpl_req.pe.tx_id = td.tx_hash();
+ tmpl_req.pe.tx_out_index = td.m_internal_output_index;
+ tmpl_req.pe.wallet_index = cxt.index;
// mark stake source as spent and make sure it will be restored in case of error
const std::vector stake_transfer_idx_vec{ cxt.index };
mark_transfers_as_spent(stake_transfer_idx_vec, "stake source");
bool gracefull_leaving = false;
- auto stake_transfer_spent_flag_restorer = epee::misc_utils::create_scope_leave_handler([&](){
+ auto stake_transfer_spent_flag_restorer = epee::misc_utils::create_scope_leave_handler([&]() {
if (!gracefull_leaving)
clear_transfers_from_flag(stake_transfer_idx_vec, WALLET_TRANSFER_DETAIL_FLAG_SPENT, "stake source");
- });
+ });
// generate UTXO Defragmentation Transaction - to reduce the UTXO set size
transaction udtx{};
@@ -5183,15 +5266,16 @@ bool wallet2::build_minted_block(const mining_context& cxt, const currency::acco
subm_req.b = t_serializable_object_to_blob(b);
if (tmpl_req.explicit_transaction.size())
subm_req.explicit_txs.push_back(hexemizer{ tmpl_req.explicit_transaction });
-
+
m_core_proxy->call_COMMAND_RPC_SUBMITBLOCK2(subm_req, subm_rsp);
if (subm_rsp.status != API_RETURN_CODE_OK)
{
WLT_LOG_ERROR("Constructed block " << print16(block_hash) << " was rejected by the core, status: " << subm_rsp.status);
return false;
- }
+ }
WLT_LOG_GREEN("PoS block " << print16(block_hash) << " generated and accepted, congrats!", LOG_LEVEL_0);
- m_wcallback->on_pos_block_found(b);
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_pos_block_found(b);
gracefull_leaving = true; // to prevent source transfer flags be cleared in scope leave handler
return true;
@@ -5228,13 +5312,13 @@ bool wallet2::is_transfer_unlocked(const transfer_details& td) const
//----------------------------------------------------------------------------------------------------
bool wallet2::is_transfer_unlocked(const transfer_details& td, bool for_pos_mining, uint64_t& stake_lock_time) const
{
- if (td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_BLOCKED)
- return false;
+ if (td.m_flags & WALLET_TRANSFER_DETAIL_FLAG_BLOCKED)
+ return false;
if (td.m_ptx_wallet_info->m_block_height + WALLET_DEFAULT_TX_SPENDABLE_AGE > get_blockchain_current_size())
return false;
-
+
uint64_t unlock_time = get_tx_unlock_time(td.m_ptx_wallet_info->m_tx, td.m_internal_output_index);
if (for_pos_mining && m_core_runtime_config.is_hardfork_active_for_height(1, get_blockchain_current_size()))
@@ -5345,7 +5429,7 @@ uint64_t wallet2::get_alias_cost(const std::string& alias)
{
throw std::runtime_error(std::string("Failed to get alias cost"));
}
-
+
return rsp.reward;
}
//----------------------------------------------------------------------------------------------------
@@ -5402,13 +5486,44 @@ void wallet2::request_alias_registration(currency::extra_alias_entry& ai, curren
transfer(destinations, 0, 0, fee, extra, attachments, get_current_split_strategy(), tx_dust_policy(DEFAULT_DUST_THRESHOLD), res_tx, CURRENCY_TO_KEY_OUT_RELAXED, false);
}
//----------------------------------------------------------------------------------------------------
+void wallet2::fill_ado_version_based_onhardfork(currency::asset_descriptor_operation& asset_reg_info)
+{
+ if (!is_in_hardfork_zone(ZANO_HARDFORK_05))
+ {
+ asset_reg_info.version = ASSET_DESCRIPTOR_OPERATION_HF4_VER;
+ }
+ else
+ {
+ asset_reg_info.version = ASSET_DESCRIPTOR_OPERATION_LAST_VER;
+ }
+}
+//----------------------------------------------------------------------------------------------------
+void wallet2::fill_adb_version_based_onhardfork(currency::asset_descriptor_base& asset_base)
+{
+ if (!is_in_hardfork_zone(ZANO_HARDFORK_05))
+ {
+ asset_base.version = ASSET_DESCRIPTOR_BASE_HF4_VER;
+ }
+ else
+ {
+ asset_base.version = ASSET_DESCRIPTOR_BASE_LAST_VER;
+ }
+}
+//----------------------------------------------------------------------------------------------------
void wallet2::deploy_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector& destinations, currency::finalized_tx& ft, crypto::public_key& new_asset_id)
{
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(asset_info.decimal_point <= 18, "too big decimal point: " << (int)asset_info.decimal_point);
+ WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(validate_asset_ticker_and_full_name(asset_info), "ticker or full_name are invalid (perhaps they contain invalid symbols)");
asset_descriptor_operation asset_reg_info{};
- asset_reg_info.descriptor = asset_info;
+ fill_ado_version_based_onhardfork(asset_reg_info);
+ asset_reg_info.opt_descriptor = asset_info;
+ fill_adb_version_based_onhardfork(*asset_reg_info.opt_descriptor);
asset_reg_info.operation_type = ASSET_DESCRIPTOR_OPERATION_REGISTER;
+ if (is_in_hardfork_zone(ZANO_HARDFORK_05))
+ {
+ asset_reg_info.opt_asset_id_salt = crypto::rand();
+ }
construct_tx_param ctp = get_default_construct_tx_param();
ctp.dsts = destinations;
ctp.extra.push_back(asset_reg_info);
@@ -5422,7 +5537,7 @@ void wallet2::deploy_new_asset(const currency::asset_descriptor_base& asset_info
CHECK_AND_ASSERT_THROW_MES(r, "asset_descriptor_operation cannot be found in tx extra as expected");
CHECK_AND_ASSERT_THROW_MES(get_or_calculate_asset_id(ado, nullptr, &new_asset_id), "get_or_calculate_asset_id failed");
- m_custom_assets[new_asset_id] = ado.descriptor;
+ m_custom_assets[new_asset_id] = *ado.opt_descriptor;
}
//----------------------------------------------------------------------------------------------------
void wallet2::deploy_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector& destinations, currency::transaction& result_tx, crypto::public_key& new_asset_id)
@@ -5436,12 +5551,19 @@ void wallet2::emit_asset(const crypto::public_key& asset_id, const std::vectorsecond.thirdparty_custody || own_asset_entry_it->second.owner_eth_pub_key.has_value() )
{
send_to_network = false;
ctp.additional_transfer_flags_to_mark = WALLET_TRANSFER_DETAIL_FLAG_ASSET_OP_RESERVATION;
- ctp.tx_meaning_for_logs = "asset eth emission";
+ ctp.tx_meaning_for_logs = "asset thirdparty/eth emission";
+ ctp.ado_sign_thirdparty = true;
}
this->transfer(ctp, ft, send_to_network, nullptr);
@@ -5477,7 +5600,9 @@ void wallet2::update_asset(const crypto::public_key& asset_id, const currency::a
CHECK_AND_ASSERT_THROW_MES(r, "Failed to get asset info from daemon");
asset_descriptor_operation asset_update_info{};
- asset_update_info.descriptor = new_descriptor;
+ fill_ado_version_based_onhardfork(asset_update_info);
+ asset_update_info.opt_descriptor = new_descriptor;
+ fill_adb_version_based_onhardfork(*asset_update_info.opt_descriptor);
asset_update_info.operation_type = ASSET_DESCRIPTOR_OPERATION_UPDATE;
asset_update_info.opt_asset_id = asset_id;
construct_tx_param ctp = get_default_construct_tx_param();
@@ -5512,14 +5637,16 @@ void wallet2::transfer_asset_ownership(const crypto::public_key& asset_id, const
CHECK_AND_ASSERT_THROW_MES(r, "Failed to get asset info from daemon");
asset_descriptor_operation asset_update_info{};
- asset_update_info.descriptor = last_adb;
+ fill_ado_version_based_onhardfork(asset_update_info);
+ asset_update_info.opt_descriptor = last_adb;
+ fill_adb_version_based_onhardfork(*asset_update_info.opt_descriptor);
asset_update_info.operation_type = ASSET_DESCRIPTOR_OPERATION_UPDATE;
asset_update_info.opt_asset_id = asset_id;
if (new_owner_v.type() == typeid(crypto::public_key))
- asset_update_info.descriptor.owner = boost::get(new_owner_v);
+ asset_update_info.opt_descriptor->owner = boost::get(new_owner_v);
else
- asset_update_info.descriptor.owner_eth_pub_key = boost::get(new_owner_v);
+ asset_update_info.opt_descriptor->owner_eth_pub_key = boost::get(new_owner_v);
construct_tx_param ctp = get_default_construct_tx_param();
ctp.extra.push_back(asset_update_info);
@@ -5543,17 +5670,21 @@ void wallet2::transfer_asset_ownership(const crypto::public_key& asset_id, const
result_tx = ft.tx;
}
//----------------------------------------------------------------------------------------------------
-void wallet2::burn_asset(const crypto::public_key& asset_id, uint64_t amount_to_burn, currency::finalized_tx& ft)
+void wallet2::burn_asset(const crypto::public_key& asset_id, uint64_t amount_to_burn, currency::finalized_tx& ft, const std::vector& service_entries, const std::string& address_to_point/* = const std::string()*/, uint64_t native_amount_to_point/* = 0*/)
{
- currency::asset_descriptor_base last_adb{};
- bool r = this->daemon_get_asset_info(asset_id, last_adb);
- CHECK_AND_ASSERT_THROW_MES(r, "Failed to get asset info from daemon");
-
asset_descriptor_operation asset_burn_info{};
- asset_burn_info.descriptor = last_adb;
-
- CHECK_AND_ASSERT_THROW_MES(last_adb.current_supply >= amount_to_burn, "amount_to_burn is incorrect: " << print_money_brief(amount_to_burn, last_adb.decimal_point) << ", current_supply: " << print_money_brief(last_adb.current_supply, last_adb.decimal_point));
+ fill_ado_version_based_onhardfork(asset_burn_info);
+ if (!is_in_hardfork_zone(ZANO_HARDFORK_05))
+ {
+ currency::asset_descriptor_base last_adb{};
+ bool r = this->daemon_get_asset_info(asset_id, last_adb);
+ CHECK_AND_ASSERT_THROW_MES(r, "Failed to get asset info from daemon");
+ asset_burn_info.opt_descriptor = last_adb;
+ fill_adb_version_based_onhardfork(*asset_burn_info.opt_descriptor);
+ CHECK_AND_ASSERT_THROW_MES(last_adb.current_supply >= amount_to_burn, "amount_to_burn is incorrect: " << print_money_brief(amount_to_burn, last_adb.decimal_point) << ", current_supply: " << print_money_brief(last_adb.current_supply, last_adb.decimal_point));
+ }
+
currency::tx_destination_entry dst_to_burn{};
dst_to_burn.amount = amount_to_burn;
dst_to_burn.asset_id = asset_id;
@@ -5565,14 +5696,30 @@ void wallet2::burn_asset(const crypto::public_key& asset_id, uint64_t amount_to_
ctp.need_at_least_1_zc = true;
ctp.dsts.push_back(dst_to_burn);
ctp.tx_meaning_for_logs = "asset burn";
+ if (service_entries.size())
+ {
+ //put it to extra
+ ctp.extra.insert(ctp.extra.end(), service_entries.begin(), service_entries.end());
+ }
+ if (address_to_point.size())
+ {
+ currency::account_public_address addr = AUTO_VAL_INIT(addr);
+ bool r = currency::get_account_address_from_str(addr, address_to_point);
+ CHECK_AND_ASSERT_THROW_MES(r, "WRONG_ADDRESS");
+ currency::tx_destination_entry dst_to_point = AUTO_VAL_INIT(dst_to_point);
+ dst_to_point.asset_id = native_coin_asset_id;
+ dst_to_point.amount = native_amount_to_point;
+ dst_to_point.addr.push_back(addr);
+ ctp.dsts.push_back(dst_to_point);
+ }
this->transfer(ctp, ft, true, nullptr);
}
//----------------------------------------------------------------------------------------------------
-void wallet2::burn_asset(const crypto::public_key& asset_id, uint64_t amount_to_burn, currency::transaction& result_tx)
+void wallet2::burn_asset(const crypto::public_key& asset_id, uint64_t amount_to_burn, currency::transaction& result_tx, const std::vector& service_entries, const std::string& address_to_point/* = const std::string()*/, uint64_t native_amount_to_point /*= 0*/)
{
finalized_tx ft{};
- burn_asset(asset_id, amount_to_burn, ft);
+ burn_asset(asset_id, amount_to_burn, ft, service_entries, address_to_point, native_amount_to_point);
result_tx = ft.tx;
}
//----------------------------------------------------------------------------------------------------
@@ -5594,14 +5741,14 @@ void wallet2::request_alias_update(currency::extra_alias_entry& ai, currency::tr
COMMAND_RPC_GET_ALIAS_DETAILS::response rsp = AUTO_VAL_INIT(rsp);
bool r = m_core_proxy->call_COMMAND_RPC_GET_ALIAS_DETAILS(req, rsp);
CHECK_AND_ASSERT_THROW_MES(r, "Failed to call_COMMAND_RPC_GET_ALIAS_DETAILS");
-
+
CHECK_AND_ASSERT_THROW_MES(rsp.status == API_RETURN_CODE_OK, "call_COMMAND_RPC_GET_ALIAS_DETAILS response: " << rsp.status);
-
+
currency::account_public_address addr = AUTO_VAL_INIT(addr);
currency::get_account_address_from_str(addr, rsp.alias_details.address);
- CHECK_AND_ASSERT_THROW_MES(m_account.get_public_address().spend_public_key == addr.spend_public_key &&
+ CHECK_AND_ASSERT_THROW_MES(m_account.get_public_address().spend_public_key == addr.spend_public_key &&
m_account.get_public_address().view_public_key == addr.view_public_key, "call_COMMAND_RPC_GET_ALIAS_DETAILS: ownership is not confirmed");
if (!validate_alias_name(ai.m_alias))
@@ -5616,7 +5763,7 @@ void wallet2::request_alias_update(currency::extra_alias_entry& ai, currency::tr
<< "signed(owner) pub key: " << m_account.get_keys().account_address.spend_public_key << ENDL
<< "transfered to address: " << get_account_address_as_str(ai.m_address) << ENDL
<< "sign_buff_hash: " << currency::get_sign_buff_hash_for_alias_update(ai)
- );
+ );
std::vector destinations;
std::vector extra;
@@ -5628,7 +5775,7 @@ void wallet2::request_alias_update(currency::extra_alias_entry& ai, currency::tr
}
//----------------------------------------------------------------------------------------------------
bool wallet2::check_available_sources(std::list& amounts)
-{
+{
/*
std::list > holds;
amounts.sort();
@@ -5651,7 +5798,7 @@ bool wallet2::check_available_sources(std::list& amounts)
clear_transfers_from_flag(h, WALLET_TRANSFER_DETAIL_FLAG_BLOCKED, "check_available_sources");
add_transfers_to_transfers_cache(h);
}
-
+
WLT_LOG_MAGENTA("[CHECK_AVAILABLE_SOURCES]: " << amounts << " res: " << res << ENDL <<" holds: " << holds, LOG_LEVEL_0);
return res;
@@ -5683,28 +5830,34 @@ void wallet2::dump_trunsfers(std::stringstream& ss, bool verbose) const
{
if (verbose)
{
- std::string res_buff;
- local_transfers_struct lt(const_cast(m_transfers));
- epee::serialization::store_t_to_json(lt, res_buff);
- ss << res_buff;
+
+ ss << "{ \"transfers\": [" << ENDL;
+ for (const auto& tr : m_transfers)
+ {
+ uint64_t i = tr.first;
+ const transfer_details& td = tr.second;
+ ss << "{ \"i\": " << i << "," << ENDL;
+ ss << "\"entry\": " << epee::serialization::store_t_to_json(td) << "}," << ENDL;
+ }
}
else
{
boost::io::ios_flags_saver ifs(ss);
ss << "index amount spent_h g_index block block_ts flg tx out# key image" << ENDL;
- for (size_t i = 0; i != m_transfers.size(); i++)
+ for (const auto& tr : m_transfers)
{
- const transfer_details& td = m_transfers[i];
+ uint64_t i = tr.first;
+ const transfer_details& td = tr.second;
ss << std::right <<
- std::setw(5) << i << " " <<
- std::setw(21) << print_money(td.amount()) << " " <<
- std::setw(7) << td.m_spent_height << " " <<
- std::setw(7) << td.m_global_output_index << " " <<
- std::setw(6) << td.m_ptx_wallet_info->m_block_height << " " <<
- std::setw(10) << td.m_ptx_wallet_info->m_block_timestamp << " " <<
- std::setw(4) << td.m_flags << " " <<
- get_transaction_hash(td.m_ptx_wallet_info->m_tx) << " " <<
- std::setw(4) << td.m_internal_output_index << " " <<
+ std::setw(5) << i << " " <<
+ std::setw(21) << print_money(td.amount()) << " " <<
+ std::setw(7) << td.m_spent_height << " " <<
+ std::setw(7) << td.m_global_output_index << " " <<
+ std::setw(6) << td.m_ptx_wallet_info->m_block_height << " " <<
+ std::setw(10) << td.m_ptx_wallet_info->m_block_timestamp << " " <<
+ std::setw(4) << td.m_flags << " " <<
+ get_transaction_hash(td.m_ptx_wallet_info->m_tx) << " " <<
+ std::setw(4) << td.m_internal_output_index << " " <<
td.m_key_image << ENDL;
}
}
@@ -5719,7 +5872,7 @@ std::string wallet2::dump_trunsfers(bool verbose) const
//----------------------------------------------------------------------------------------------------
void wallet2::dump_key_images(std::stringstream& ss)
{
- for (auto& ki: m_key_images)
+ for (auto& ki : m_key_images)
{
ss << "[" << ki.first << "]: " << ki.second << ENDL;
}
@@ -5755,7 +5908,7 @@ void wallet2::build_escrow_release_templates(crypto::hash multisig_id,
//generate normal escrow release
construct_params.dsts[0].amount = ecrow_details.amount_a_pledge;
construct_params.dsts[1].amount = ecrow_details.amount_b_pledge + ecrow_details.amount_to_pay;
-
+
//in case of ecrow_details.amount_a_pledge == 0 then exclude a
if (construct_params.dsts[0].amount == 0)
construct_params.dsts.erase(construct_params.dsts.begin());
@@ -5846,7 +5999,7 @@ void wallet2::build_escrow_template(const bc_services::contract_private_details&
uint64_t b_release_fee,
const std::string& payment_id,
currency::transaction& tx,
- std::vector& selected_transfers,
+ std::vector& selected_transfers,
crypto::secret_key& one_time_key)
{
construct_tx_param ctp = AUTO_VAL_INIT(ctp);
@@ -5900,10 +6053,10 @@ void wallet2::add_transfers_to_expiration_list(const std::vector& sele
{
// check all elements in selected_transfers for being already mentioned in m_money_expirations
std::vector selected_transfers_local;
- for(auto transfer_index : selected_transfers)
+ for (auto transfer_index : selected_transfers)
{
bool found = false;
- for(auto it = m_money_expirations.begin(); !found && it != m_money_expirations.end(); ++it)
+ for (auto it = m_money_expirations.begin(); !found && it != m_money_expirations.end(); ++it)
{
auto& st = it->selected_transfers;
found = std::find(st.begin(), st.end(), transfer_index) != st.end();
@@ -5924,13 +6077,13 @@ void wallet2::add_transfers_to_expiration_list(const std::vector& sele
std::stringstream ss;
for (auto tr_ind : m_money_expirations.back().selected_transfers)
{
- THROW_IF_FALSE_WALLET_INT_ERR_EX(tr_ind < m_transfers.size(), "invalid transfer index");
- uint32_t flags_before = m_transfers[tr_ind].m_flags;
- m_transfers[tr_ind].m_flags |= WALLET_TRANSFER_DETAIL_FLAG_BLOCKED;
- m_transfers[tr_ind].m_flags |= WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION;
- ss << " " << std::right << std::setw(4) << tr_ind << " " << std::setw(21) << print_money(m_transfers[tr_ind].amount()) << " "
- << std::setw(2) << std::left << flags_before << " -> " << std::setw(2) << std::left << m_transfers[tr_ind].m_flags << " "
- << get_transaction_hash(m_transfers[tr_ind].m_ptx_wallet_info->m_tx) << std::endl;
+ //THROW_IF_FALSE_WALLET_INT_ERR_EX(tr_ind < m_transfers.size(), "invalid transfer index");
+ uint32_t flags_before = m_transfers.at(tr_ind).m_flags;
+ m_transfers.at(tr_ind).m_flags |= WALLET_TRANSFER_DETAIL_FLAG_BLOCKED;
+ m_transfers.at(tr_ind).m_flags |= WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION;
+ ss << " " << std::right << std::setw(4) << tr_ind << " " << std::setw(21) << print_money(m_transfers.at(tr_ind).amount()) << " "
+ << std::setw(2) << std::left << flags_before << " -> " << std::setw(2) << std::left << m_transfers.at(tr_ind).m_flags << " "
+ << get_transaction_hash(m_transfers.at(tr_ind).m_ptx_wallet_info->m_tx) << std::endl;
}
WLT_LOG_GREEN(m_money_expirations.back().selected_transfers.size() << " transfer(s) added to expiration list:" << ENDL <<
"index amount flags tx hash" << ENDL <<
@@ -5939,14 +6092,15 @@ void wallet2::add_transfers_to_expiration_list(const std::vector& sele
//----------------------------------------------------------------------------------------------------
void wallet2::remove_transfer_from_expiration_list(uint64_t transfer_index)
{
- THROW_IF_FALSE_WALLET_INT_ERR_EX(transfer_index < m_transfers.size(), "invalid transfer index");
- for(auto it = m_money_expirations.begin(); it != m_money_expirations.end(); /* nothing */)
+ //THROW_IF_FALSE_WALLET_INT_ERR_EX(transfer_index < m_transfers.size(), "invalid transfer index");
+ auto& tr_entry = m_transfers.at(transfer_index);
+ for (auto it = m_money_expirations.begin(); it != m_money_expirations.end(); /* nothing */)
{
auto& st = it->selected_transfers;
auto jt = std::find(st.begin(), st.end(), transfer_index);
if (jt != st.end())
{
- WLT_LOG_GREEN("Transfer [" << transfer_index << "], amount: " << print_money(m_transfers[transfer_index].amount()) << ", tx: " << get_transaction_hash(m_transfers[transfer_index].m_ptx_wallet_info->m_tx) <<
+ WLT_LOG_GREEN("Transfer [" << transfer_index << "], amount: " << print_money(tr_entry.amount()) << ", tx: " << get_transaction_hash(tr_entry.m_ptx_wallet_info->m_tx) <<
" was removed from the expiration list", LOG_LEVEL_0);
st.erase(jt);
if (st.empty())
@@ -5958,20 +6112,20 @@ void wallet2::remove_transfer_from_expiration_list(uint64_t transfer_index)
++it;
}
// clear proposal reservation flag and blocked flag
- uint32_t flags_before = m_transfers[transfer_index].m_flags;
- m_transfers[transfer_index].m_flags &= ~WALLET_TRANSFER_DETAIL_FLAG_BLOCKED;
- m_transfers[transfer_index].m_flags &= ~WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION;
- if (flags_before != m_transfers[transfer_index].m_flags)
+ uint32_t flags_before = tr_entry.m_flags;
+ tr_entry.m_flags &= ~WALLET_TRANSFER_DETAIL_FLAG_BLOCKED;
+ tr_entry.m_flags &= ~WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION;
+ if (flags_before != tr_entry.m_flags)
{
- WLT_LOG_BLUE("Transfer [" << transfer_index << "] was cleared from escrow proposal reservation, flags: " << flags_before << " -> " << m_transfers[transfer_index].m_flags << ", reason: intentional removing from expiration list", LOG_LEVEL_0);
+ WLT_LOG_BLUE("Transfer [" << transfer_index << "] was cleared from escrow proposal reservation, flags: " << flags_before << " -> " << tr_entry.m_flags << ", reason: intentional removing from expiration list", LOG_LEVEL_0);
}
-
+
// (don't change m_spent flag, because transfer status is unclear - the caller should take care of it)
}
//----------------------------------------------------------------------------------------------------
void wallet2::send_escrow_proposal(const wallet_public::create_proposal_param& wp,
- currency::transaction &proposal_tx,
- currency::transaction &escrow_template_tx)
+ currency::transaction& proposal_tx,
+ currency::transaction& escrow_template_tx)
{
return send_escrow_proposal(wp.details, wp.fake_outputs_count, wp.unlock_time, wp.expiration_period, wp.fee, wp.b_fee, wp.payment_id, proposal_tx, escrow_template_tx);
}
@@ -5983,8 +6137,8 @@ void wallet2::send_escrow_proposal(const bc_services::contract_private_details&
uint64_t fee,
uint64_t b_release_fee,
const std::string& payment_id,
- currency::transaction &tx,
- currency::transaction &template_tx)
+ currency::transaction& tx,
+ currency::transaction& template_tx)
{
if (!is_connected_to_net())
{
@@ -6026,9 +6180,9 @@ void wallet2::send_escrow_proposal(const bc_services::contract_private_details&
ftp.tx_version = this->get_current_tx_version();
try
{
- prepare_transaction(ctp, ftp);
- crypto::secret_key sk = AUTO_VAL_INIT(sk);
- finalize_transaction(ftp, tx, sk, false);
+ prepare_transaction(ctp, ftp);
+ crypto::secret_key sk = AUTO_VAL_INIT(sk);
+ finalize_transaction(ftp, tx, sk, false);
}
catch (...)
{
@@ -6038,14 +6192,14 @@ void wallet2::send_escrow_proposal(const bc_services::contract_private_details&
}
send_transaction_to_network(tx);
-
+
mark_transfers_as_spent(ftp.selected_transfers, std::string("escrow proposal sent, tx <") + epee::string_tools::pod_to_hex(get_transaction_hash(tx)) + ">, contract: " + epee::string_tools::pod_to_hex(ms_id));
add_sent_tx_detailed_info(tx, ftp.attachments, ftp.prepared_destinations, ftp.selected_transfers);
print_tx_sent_message(tx, "from multisig", true, fee);
}
//----------------------------------------------------------------------------------------------------
-void wallet2::create_htlc_proposal(uint64_t amount, const currency::account_public_address& addr, uint64_t lock_blocks_count, currency::transaction &tx, const crypto::hash& htlc_hash, std::string &origin)
+void wallet2::create_htlc_proposal(uint64_t amount, const currency::account_public_address& addr, uint64_t lock_blocks_count, currency::transaction& tx, const crypto::hash& htlc_hash, std::string& origin)
{
construct_tx_param ctp = get_default_construct_tx_param();
ctp.fee = TX_DEFAULT_FEE;
@@ -6056,7 +6210,7 @@ void wallet2::create_htlc_proposal(uint64_t amount, const currency::account_publ
htlc_option.expiration = lock_blocks_count; //about 12 hours
htlc_option.htlc_hash = htlc_hash;
- currency::create_and_add_tx_payer_to_container_from_address(ctp.extra,
+ currency::create_and_add_tx_payer_to_container_from_address(ctp.extra,
get_account().get_keys().account_address, get_top_block_height(), get_core_runtime_config());
finalized_tx ft = AUTO_VAL_INIT(ft);
@@ -6069,8 +6223,12 @@ void wallet2::get_list_of_active_htlc(std::list&
{
for (auto htlc_entry : m_active_htlcs_txid)
{
- const transfer_details& td = m_transfers[htlc_entry.second];
- if (only_redeem_txs && !(td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM))
+ //auto it = m_transfers.find(htlc_entry.second);
+ //if (it == m_transfers.end())
+ // continue;
+ //const transfer_details& td = it->second;
+ const transfer_details& td = m_transfers.at(htlc_entry.second);
+ if (only_redeem_txs && !(td.m_flags & WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM))
{
continue;
}
@@ -6088,12 +6246,12 @@ void wallet2::get_list_of_active_htlc(std::list&
"[get_list_of_active_htlc]Internal error: unexpected type of out");
const txout_htlc& htlc = boost::get(out_b.target);
entry.sha256_hash = htlc.htlc_hash;
-
+
currency::tx_payer payer = AUTO_VAL_INIT(payer);
if (currency::get_type_in_variant_container(td.varian_options, payer))
entry.counterparty_address = payer.acc_addr;
- entry.is_redeem = td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM ? true : false;
+ entry.is_redeem = td.m_flags & WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM ? true : false;
htlcs.push_back(entry);
}
}
@@ -6118,7 +6276,7 @@ void wallet2::redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& ori
WLT_THROW_IF_FALSE_WITH_CODE(it != m_active_htlcs_txid.end(),
"htlc not found with tx_id = " << htlc_tx_id, API_RETURN_CODE_NOT_FOUND);
- ctp.dsts.back().amount = m_transfers[it->second].amount() - ctp.fee;
+ ctp.dsts.back().amount = m_transfers.at(it->second).amount() - ctp.fee;
this->transfer(ctp, result_tx, true, nullptr);
}
//----------------------------------------------------------------------------------------------------
@@ -6130,7 +6288,7 @@ bool wallet2::check_htlc_redeemed(const crypto::hash& htlc_tx_id, std::string& o
"htlc not found with tx_id = " << htlc_tx_id, API_RETURN_CODE_NOT_FOUND);
transfer_details_extra_option_htlc_info htlc_options = AUTO_VAL_INIT(htlc_options);
- if (!currency::get_type_in_variant_container(m_transfers[it->second].varian_options, htlc_options))
+ if (!currency::get_type_in_variant_container(m_transfers.at(it->second).varian_options, htlc_options))
{
return false;
}
@@ -6146,7 +6304,7 @@ bool wallet2::check_htlc_redeemed(const crypto::hash& htlc_tx_id, std::string& o
bool wallet2::create_ionic_swap_proposal(const wallet_public::ionic_swap_proposal_info& proposal_details, const currency::account_public_address& destination_addr, wallet_public::ionic_swap_proposal& proposal)
{
std::vector selected_transfers_for_template;
-
+
return build_ionic_swap_template(proposal_details, destination_addr, proposal, selected_transfers_for_template);
//const uint32_t mask_to_mark_escrow_template_locked_transfers = WALLET_TRANSFER_DETAIL_FLAG_BLOCKED | WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION;
@@ -6161,13 +6319,13 @@ bool wallet2::build_ionic_swap_template(const wallet_public::ionic_swap_proposal
WLT_THROW_IF_FALSE_WITH_CODE(proposal_detais.fee_paid_by_a >= get_current_minimum_network_fee(), "Error at build_ionic_swap_template, ", API_RETURN_CODE_WALLET_FEE_TOO_LOW);
construct_tx_param ctp = get_default_construct_tx_param();
-
+
//ctp.fake_outputs_count = proposal_detais.mixins;
ctp.fee = proposal_detais.fee_paid_by_a;
ctp.flags = TX_FLAG_SIGNATURE_MODE_SEPARATE;
ctp.mark_tx_as_complete = false;
ctp.crypt_address = destination_addr;
-
+
ctp.dsts.resize(proposal_detais.to_finalizer.size() + proposal_detais.to_initiator.size());
size_t i = 0;
// Here is an proposed for exchange funds
@@ -6188,7 +6346,7 @@ bool wallet2::build_ionic_swap_template(const wallet_public::ionic_swap_proposal
ctp.dsts[i].flags |= tx_destination_entry_flags::tdef_explicit_amount_to_provide;
ctp.dsts[i].addr.push_back(m_account.get_public_address());
ctp.dsts[i].asset_id = proposal_detais.to_initiator[j].asset_id;
- for_expiration_list.push_back(payment_details_subtransfer{ ctp.dsts[i].asset_id, ctp.dsts[i].amount});
+ for_expiration_list.push_back(payment_details_subtransfer{ ctp.dsts[i].asset_id, ctp.dsts[i].amount });
}
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
@@ -6199,8 +6357,8 @@ bool wallet2::build_ionic_swap_template(const wallet_public::ionic_swap_proposal
selected_transfers = ftp.selected_transfers;
currency::finalized_tx finalize_result = AUTO_VAL_INIT(finalize_result);
finalize_transaction(ftp, finalize_result, false);
- for(uint64_t i: selected_transfers)
- m_transfers[i].m_flags &= ~WALLET_TRANSFER_DETAIL_FLAG_BLOCKED;
+ for (uint64_t i : selected_transfers)
+ m_transfers.at(i).m_flags &= ~WALLET_TRANSFER_DETAIL_FLAG_BLOCKED;
//add_transfers_to_expiration_list(selected_transfers, for_expiration_list, this->get_core_runtime_config().get_core_time() + proposal_detais.expiration_time, currency::null_hash);
@@ -6210,11 +6368,11 @@ bool wallet2::build_ionic_swap_template(const wallet_public::ionic_swap_proposal
ispc.gen_context = finalize_result.ftp.gen_context;
//ispc.one_time_skey = finalize_result.one_time_key;
std::string proposal_context_blob = t_serializable_object_to_blob(ispc);
- proposal.encrypted_context = crypto::chacha_crypt(static_cast(proposal_context_blob), finalize_result.derivation);
+ proposal.encrypted_context = crypto::chacha_crypt(static_cast(proposal_context_blob), finalize_result.derivation);
return true;
}
//----------------------------------------------------------------------------------------------------
-bool wallet2::get_ionic_swap_proposal_info(const std::string&raw_proposal, wallet_public::ionic_swap_proposal_info& proposal_info) const
+bool wallet2::get_ionic_swap_proposal_info(const std::string& raw_proposal, wallet_public::ionic_swap_proposal_info& proposal_info) const
{
wallet_public::ionic_swap_proposal proposal = AUTO_VAL_INIT(proposal);
bool r = t_unserializable_object_from_blob(proposal, raw_proposal);
@@ -6255,7 +6413,7 @@ bool wallet2::get_ionic_swap_proposal_info(const wallet_public::ionic_swap_propo
std::unordered_map ammounts_to_b; //amounts to Bob (the one who received proposal), should BE funded
std::vector bob_outs;
bob_outs.resize(proposal.tx_template.vout.size());
-
+
for (const auto& o : outs)
{
THROW_IF_FALSE_WALLET_INT_ERR_EX(ionic_context.gen_context.asset_ids.size() > o.index, "Tx gen context has mismatch with tx(asset_ids) ");
@@ -6306,7 +6464,7 @@ bool wallet2::get_ionic_swap_proposal_info(const wallet_public::ionic_swap_propo
return false;
}
amounts_provided_by_a[in_asset_id] += amount;
-
+
//if (proposal_info.mixins == 0 || proposal_info.mixins > mx)
//{
// proposal_info.mixins = mx;
@@ -6328,9 +6486,9 @@ bool wallet2::get_ionic_swap_proposal_info(const wallet_public::ionic_swap_propo
{
uint64_t amount_sent_back_to_initiator = ammounts_to_a[a.first];
- if (amounts_provided_by_a[a.first] < (a.second + amount_sent_back_to_initiator) )
+ if (amounts_provided_by_a[a.first] < (a.second + amount_sent_back_to_initiator))
{
- WLT_LOG_RED("Amount[" << a.first << "] provided by Alice(" << amounts_provided_by_a[a.first] << ") is less then transfered to Bob(" << a.second <<")", LOG_LEVEL_0);
+ WLT_LOG_RED("Amount[" << a.first << "] provided by Alice(" << amounts_provided_by_a[a.first] << ") is less then transfered to Bob(" << a.second << ")", LOG_LEVEL_0);
return false;
}
amounts_provided_by_a[a.first] -= (amount_sent_back_to_initiator + a.second);
@@ -6357,7 +6515,7 @@ bool wallet2::get_ionic_swap_proposal_info(const wallet_public::ionic_swap_propo
proposal_info.to_initiator.push_back(view::asset_funds{ a.first, a.second - amounts_provided_by_a[a.first] });
}
-
+
return true;
}
@@ -6413,7 +6571,7 @@ bool wallet2::accept_ionic_swap_proposal(const wallet_public::ionic_swap_proposa
construct_tx_param construct_param = get_default_construct_tx_param();
construct_param.fee = additional_fee;
-
+
crypto::secret_key one_time_key = ionic_context.gen_context.tx_key.sec; // TODO: figure out this mess with tx sec key -- sowle
construct_param.crypt_address = m_account.get_public_address();
construct_param.flags = TX_FLAG_SIGNATURE_MODE_SEPARATE;
@@ -6423,7 +6581,7 @@ bool wallet2::accept_ionic_swap_proposal(const wallet_public::ionic_swap_proposa
//build transaction
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
ftp.tx_version = this->get_current_tx_version();
- ftp.gen_context = ionic_context.gen_context;
+ ftp.gen_context = ionic_context.gen_context;
prepare_transaction(construct_param, ftp, msc);
@@ -6478,9 +6636,12 @@ bool wallet2::prepare_tx_sources_for_defragmentation_tx(std::vector= LOG_LEVEL_2)
ss << "preparing sources for utxo defragmentation tx:";
- for (size_t i = 0, size = m_transfers.size(); i < size && selected_indicies.size() < m_max_utxo_count_for_defragmentation_tx; ++i)
+ for (const auto& tr : m_transfers)//size_t i = 0, size = m_transfers .size(); i < size && selected_indicies.size() < m_max_utxo_count_for_defragmentation_tx; ++i)
{
- const auto& td = m_transfers[i];
+ if (selected_indicies.size() >= m_max_utxo_count_for_defragmentation_tx)
+ break;
+ uint64_t i = tr.first;
+ const auto& td = tr.second;
if (!td.is_native_coin() || td.m_amount > m_max_allowed_output_amount_for_defragmentation_tx)
continue;
@@ -6514,7 +6675,7 @@ bool wallet2::prepare_tx_sources(assets_selection_context& needed_money_map, siz
select_transfers(needed_money_map, fake_outputs_count, dust_threshold, selected_indicies); // always returns true, TODO consider refactoring -- sowle
return prepare_tx_sources(fake_outputs_count, sources, selected_indicies);
}
- catch(...)
+ catch (...)
{
// if smth went wrong -- invalidate transfers cache to trigger its regeneration on the next use
// it is necessary because it may be in invalid state (some items might be erased within select_indices_for_transfer() or expand_selection_with_zc_input())
@@ -6529,11 +6690,11 @@ void wallet2::prefetch_global_indicies_if_needed(const std::vector& se
//std::list indices_that_requested_global_indicies;
for (uint64_t i : selected_indicies)
{
- WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(m_transfers[i].m_global_output_index != WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED,
- "m_transfers[" << i << "].m_global_output_index is WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED");
- //indices_that_requested_global_indicies.push_back(i);
- //txs.push_back(m_transfers[i].m_ptx_wallet_info->m_tx);
- //}
+ WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(m_transfers.at(i).m_global_output_index != WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED,
+ "m_transfers.at(" << i << ").m_global_output_index is WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED");
+ //indices_that_requested_global_indicies.push_back(i);
+ //txs.push_back(m_transfers.at(i).m_ptx_wallet_info->m_tx);
+ //}
}
/*
@@ -6544,7 +6705,7 @@ void wallet2::prefetch_global_indicies_if_needed(const std::vector& se
auto it_ooutputs = outputs_for_all_txs.begin();
for (; it_ooutputs != outputs_for_all_txs.end();)
{
- transfer_details& td = m_transfers[*it_indices];
+ transfer_details& td = m_transfers.at(*it_indices);
td.m_global_output_index = (*it_ooutputs)[td.m_internal_output_index];
it_ooutputs++; it_indices++;
}*/
@@ -6574,32 +6735,35 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, bool use_all_decoys
req.height_upper_limit = m_last_pow_block_h; // request decoys to be either older than, or the same age as stake output's height
req.use_forced_mix_outs = false; // TODO: add this feature to UI later
//req.decoys_count = fake_outputs_count + 1; // one more to be able to skip a decoy in case it hits the real output
- for (uint64_t i: selected_indicies)
+ for (uint64_t i : selected_indicies)
{
req.amounts.push_back(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::offsets_distribution());
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::offsets_distribution& rdisttib = req.amounts.back();
-
- auto it = m_transfers.begin() + i;
- WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->m_ptx_wallet_info->m_tx.vout.size() > it->m_internal_output_index,
- "m_internal_output_index = " << it->m_internal_output_index <<
- " is greater or equal to outputs count = " << it->m_ptx_wallet_info->m_tx.vout.size());
-
+
+ auto it = m_transfers.find(i);
+ WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it != m_transfers.end(),
+ "internal error: index in m_tranfers " << i << " not found");
+
+ WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->second.m_ptx_wallet_info->m_tx.vout.size() > it->second.m_internal_output_index,
+ "m_internal_output_index = " << it->second.m_internal_output_index <<
+ " is greater or equal to outputs count = " << it->second.m_ptx_wallet_info->m_tx.vout.size());
+
//rdisttib.own_global_index = it->m_global_output_index;
//check if we have Zarcanum era output of pre-Zarcanum
- if (it->is_zc())
+ if (it->second.is_zc())
{
- if(this->is_auditable())
+ if (this->is_auditable())
continue;
//Zarcanum era
rdisttib.amount = 0;
//generate distribution in Zarcanum hardfork
- build_distribution_for_input(rdisttib.global_offsets, it->m_global_output_index);
+ build_distribution_for_input(rdisttib.global_offsets, it->second.m_global_output_index);
need_to_request = true;
}
else
{
//for prezarcanum era use flat distribution
- rdisttib.amount = it->m_amount;
+ rdisttib.amount = it->second.m_amount;
rdisttib.global_offsets.resize(fake_outputs_count + 1, 0);
}
}
@@ -6637,7 +6801,7 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, bool use_all_decoys
if (!use_all_decoys_if_found_less_than_required)
{
// make sure we have received the requested number of decoys
- for(size_t i = 0; i != daemon_resp.outs.size(); i++)
+ for (size_t i = 0; i != daemon_resp.outs.size(); i++)
if (req.amounts[i].amount != 0 && daemon_resp.outs[i].outs.size() != req.amounts[i].global_offsets.size())
scanty_outs.push_back(daemon_resp.outs[i]);
THROW_IF_FALSE_WALLET_EX(scanty_outs.empty(), error::not_enough_outs_to_mix, scanty_outs, fake_outputs_count);
@@ -6653,19 +6817,21 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, bool use_all_decoys
size_t i = 0;
for (uint64_t J : selected_indicies)
{
- auto it = m_transfers.begin() + J;
+ auto it = m_transfers.find(J);
+ WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it != m_transfers.end(), "internal error: J " << J << " not found in m_transfers");
+
sources.push_back(AUTO_VAL_INIT(currency::tx_source_entry()));
currency::tx_source_entry& src = sources.back();
- transfer_details& td = *it;
- src.transfer_index = it - m_transfers.begin();
+ transfer_details& td = it->second;
+ src.transfer_index = J;
src.amount = td.amount();
src.asset_id = td.get_asset_id();
size_t fake_outputs_count = fake_outputs_count_;
//redefine for hardfork
if (td.is_zc() && !this->is_auditable())
fake_outputs_count = m_core_runtime_config.hf4_minimum_mixins;
-
+
//paste mixin transaction
if (daemon_resp.outs.size())
@@ -6679,18 +6845,18 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, bool use_all_decoys
{
//TODO: make sure we have exact count needed
}
-
- daemon_resp.outs[i].outs.sort([](const out_entry& a, const out_entry& b){return a.global_amount_index < b.global_amount_index; });
- for(out_entry& daemon_oe : daemon_resp.outs[i].outs)
+
+ daemon_resp.outs[i].outs.sort([](const out_entry& a, const out_entry& b) {return a.global_amount_index < b.global_amount_index; });
+ for (out_entry& daemon_oe : daemon_resp.outs[i].outs)
{
if (td.m_global_output_index == daemon_oe.global_amount_index)
continue;
tx_output_entry oe = AUTO_VAL_INIT(oe);
- oe.amount_commitment = daemon_oe.amount_commitment;
- oe.concealing_point = daemon_oe.concealing_point;
- oe.out_reference = daemon_oe.global_amount_index;
- oe.stealth_address = daemon_oe.stealth_address;
- oe.blinded_asset_id = daemon_oe.blinded_asset_id; // TODO @#@# BAD DESIGN, consider refactoring -- sowle
+ oe.amount_commitment = daemon_oe.amount_commitment;
+ oe.concealing_point = daemon_oe.concealing_point;
+ oe.out_reference = daemon_oe.global_amount_index;
+ oe.stealth_address = daemon_oe.stealth_address;
+ oe.blinded_asset_id = daemon_oe.blinded_asset_id; // TODO @#@# BAD DESIGN, consider refactoring -- sowle
src.outputs.push_back(oe);
if (src.outputs.size() >= fake_outputs_count)
break;
@@ -6699,11 +6865,11 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, bool use_all_decoys
//paste real transaction to the random index
auto it_to_insert = std::find_if(src.outputs.begin(), src.outputs.end(), [&](const tx_output_entry& a)
- {
- if (a.out_reference.type().hash_code() == typeid(uint64_t).hash_code())
- return static_cast(boost::get(a.out_reference) >= td.m_global_output_index);
- return false; // TODO: implement deterministics real output placement in case there're ref_by_id outs
- });
+ {
+ if (a.out_reference.type().hash_code() == typeid(uint64_t).hash_code())
+ return static_cast(boost::get(a.out_reference) >= td.m_global_output_index);
+ return false; // TODO: implement deterministics real output placement in case there're ref_by_id outs
+ });
//size_t real_index = src.outputs.size() ? (rand() % src.outputs.size() ):0;
tx_output_entry real_oe = AUTO_VAL_INIT(real_oe);
real_oe.out_reference = td.m_global_output_index; // TODO: use ref_by_id when neccessary
@@ -6724,17 +6890,17 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, bool use_all_decoys
VARIANT_SWITCH_END();
}
VARIANT_CASE_CONST(tx_out_zarcanum, o);
- real_oe.amount_commitment = o.amount_commitment; // TODO @#@# consider using shorter code like in sweep_below() (or better reuse it)
- real_oe.concealing_point = o.concealing_point;
- real_oe.stealth_address = o.stealth_address;
- real_oe.blinded_asset_id = o.blinded_asset_id;
- WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.is_zc(), "transfer #" << J << ", amount: " << print_money_brief(td.amount()) << " is not a ZC");
- src.real_out_amount_blinding_mask = td.m_zc_info_ptr->amount_blinding_mask;
- src.real_out_asset_id_blinding_mask = td.m_zc_info_ptr->asset_id_blinding_mask;
- src.asset_id = td.m_zc_info_ptr->asset_id;
+ real_oe.amount_commitment = o.amount_commitment; // TODO @#@# consider using shorter code like in sweep_below() (or better reuse it)
+ real_oe.concealing_point = o.concealing_point;
+ real_oe.stealth_address = o.stealth_address;
+ real_oe.blinded_asset_id = o.blinded_asset_id;
+ WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.is_zc(), "transfer #" << J << ", amount: " << print_money_brief(td.amount()) << " is not a ZC");
+ src.real_out_amount_blinding_mask = td.m_zc_info_ptr->amount_blinding_mask;
+ src.real_out_asset_id_blinding_mask = td.m_zc_info_ptr->asset_id_blinding_mask;
+ src.asset_id = td.m_zc_info_ptr->asset_id;
#ifndef NDEBUG
- WLT_CHECK_AND_ASSERT_MES(crypto::point_t(src.asset_id) + src.real_out_asset_id_blinding_mask * crypto::c_point_X == crypto::point_t(real_oe.blinded_asset_id).modify_mul8(), false, "real_out_asset_id_blinding_mask doesn't match real_oe.blinded_asset_id");
- WLT_CHECK_AND_ASSERT_MES(td.m_amount * crypto::point_t(real_oe.blinded_asset_id).modify_mul8() + src.real_out_amount_blinding_mask * crypto::c_point_G == crypto::point_t(real_oe.amount_commitment).modify_mul8(), false, "real_out_amount_blinding_mask doesn't match real_oe.amount_commitment");
+ WLT_CHECK_AND_ASSERT_MES(crypto::point_t(src.asset_id) + src.real_out_asset_id_blinding_mask * crypto::c_point_X == crypto::point_t(real_oe.blinded_asset_id).modify_mul8(), false, "real_out_asset_id_blinding_mask doesn't match real_oe.blinded_asset_id");
+ WLT_CHECK_AND_ASSERT_MES(td.m_amount * crypto::point_t(real_oe.blinded_asset_id).modify_mul8() + src.real_out_amount_blinding_mask * crypto::c_point_G == crypto::point_t(real_oe.amount_commitment).modify_mul8(), false, "real_out_amount_blinding_mask doesn't match real_oe.amount_commitment");
#endif
VARIANT_SWITCH_END();
@@ -6742,7 +6908,7 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, bool use_all_decoys
src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_ptx_wallet_info->m_tx);
src.real_output = interted_it - src.outputs.begin();
src.real_output_in_tx_index = td.m_internal_output_index;
-
+
if (epee::log_space::get_set_log_detalisation_level() >= LOG_LEVEL_1)
{
std::stringstream ss;
@@ -6750,7 +6916,7 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, bool use_all_decoys
print_source_entry(ss, src);
WLT_LOG_L1(ss.str());
}
-
+
++i;
}
return true;
@@ -6774,7 +6940,7 @@ void wallet2::select_decoys(currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS
typedef currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry out_entry;
//TODO: This strategy would be a subject for continuous refactoring
-
+
//first take all real transactions if ther are some
std::list local_outs;
std::list coinbases;
@@ -6798,7 +6964,7 @@ void wallet2::select_decoys(currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS
{
coinbases.push_back(entry);
continue;
- }
+ }
local_outs.push_back(entry);
@@ -6812,7 +6978,7 @@ void wallet2::select_decoys(currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS
}
THROW_IF_FALSE_WALLET_INT_ERR_EX(local_outs.size() == m_core_runtime_config.hf4_minimum_mixins, "Amount is not 0 in zc decoys entry");
- amount_entry.outs = local_outs;
+ amount_entry.outs = local_outs;
}
//----------------------------------------------------------------------------------------------------------------
void wallet2::build_distribution_for_input(std::vector& offsets, uint64_t own_index)
@@ -6863,10 +7029,10 @@ bool wallet2::prepare_tx_sources_htlc(crypto::hash htlc_tx_id, const std::string
"htlc not found with tx_id = " << htlc_tx_id, API_RETURN_CODE_NOT_FOUND);
}
- WLT_THROW_IF_FALSE_WITH_CODE(m_transfers.size() > it->second,
- "Internal error: index in m_active_htlcs_txid <" << it->second << "> is bigger then size of m_transfers <" << m_transfers.size() << ">", API_RETURN_CODE_INTERNAL_ERROR);
+ //WLT_THROW_IF_FALSE_WITH_CODE(m_transfers.size() > it->second,
+ // "Internal error: index in m_active_htlcs_txid <" << it->second << "> is bigger then size of m_transfers <" << m_transfers.size() << ">", API_RETURN_CODE_INTERNAL_ERROR);
- const transfer_details& td = m_transfers[it->second];
+ const transfer_details& td = m_transfers.at(it->second);
//@#@
WLT_THROW_IF_FALSE_WITH_CODE(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type() == typeid(tx_out_bare),
"Unexpected out type in prepare_tx_sources_htlc:" << td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type().name(), API_RETURN_CODE_INTERNAL_ERROR);
@@ -6876,7 +7042,7 @@ bool wallet2::prepare_tx_sources_htlc(crypto::hash htlc_tx_id, const std::string
"Unexpected type in active htlc", API_RETURN_CODE_INTERNAL_ERROR);
const txout_htlc& htlc_out = boost::get(out_bare.target);
- bool use_sha256 = !(htlc_out.flags&CURRENCY_TXOUT_HTLC_FLAGS_HASH_TYPE_MASK);
+ bool use_sha256 = !(htlc_out.flags & CURRENCY_TXOUT_HTLC_FLAGS_HASH_TYPE_MASK);
//check origin
WLT_THROW_IF_FALSE_WITH_CODE(origin.size() != 0,
@@ -6913,16 +7079,16 @@ assets_selection_context wallet2::get_needed_money(uint64_t fee, const std::vect
{
assets_selection_context amounts_map;
amounts_map[currency::native_coin_asset_id].needed_amount = fee;
- for(auto& dt : dsts)
+ for (auto& dt : dsts)
{
- if(dt.asset_id == currency::null_pkey)
+ if (dt.asset_id == currency::null_pkey)
continue; //this destination for emmition only
THROW_IF_TRUE_WALLET_EX(0 == dt.amount, error::zero_destination);
uint64_t money_to_add = dt.amount;
if (dt.amount_to_provide || dt.flags & tx_destination_entry_flags::tdef_explicit_amount_to_provide)
money_to_add = dt.amount_to_provide;
-
+
amounts_map[dt.asset_id].needed_amount += money_to_add;
THROW_IF_TRUE_WALLET_EX(amounts_map[dt.asset_id].needed_amount < money_to_add, error::tx_sum_overflow, dsts, fee);
//clean up empty entries
@@ -6941,7 +7107,8 @@ void wallet2::set_disable_tor_relay(bool disable)
//----------------------------------------------------------------------------------------------------------------
void wallet2::notify_state_change(const std::string& state_code, const std::string& details)
{
- m_wcallback->on_tor_status_change(state_code);
+ if (auto wcb = m_wcallback.lock())
+ wcb->on_tor_status_change(state_code);
}
//----------------------------------------------------------------------------------------------------------------
void wallet2::send_transaction_to_network(const transaction& tx)
@@ -6951,7 +7118,7 @@ void wallet2::send_transaction_to_network(const transaction& tx)
{
//TODO check that core synchronized
//epee::net_utils::levin_client2 p2p_client;
-
+
//make few attempts
tools::levin_over_tor_client p2p_client;
p2p_client.get_transport().set_notifier(this);
@@ -7022,8 +7189,8 @@ void wallet2::add_sent_tx_detailed_info(const transaction& tx, const std::vector
}
if (!recipients.size())
{
- //transaction send to ourself
- recipients.push_back(payment_id.empty() ? get_account_address_as_str(m_account.get_public_address()) : get_account_address_and_payment_id_as_str(m_account.get_public_address(), payment_id));
+ //transaction send to ourself
+ recipients.push_back(payment_id.empty() ? get_account_address_as_str(m_account.get_public_address()) : get_account_address_and_payment_id_as_str(m_account.get_public_address(), payment_id));
}
add_sent_unconfirmed_tx(tx, recipients, selected_transfers, destinations);
@@ -7034,18 +7201,18 @@ void wallet2::mark_transfers_with_flag(const std::vector& selected_tra
// check all selected transfers prior to flag change
for (uint64_t i : selected_transfers)
{
- WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(i < m_transfers.size(), "invalid transfer index given: " << i << ", m_transfers.size() == " << m_transfers.size());
+ //WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(i < m_transfers.size(), "invalid transfer index given: " << i << ", m_transfers.size() == " << m_transfers.size());
if (throw_if_flag_already_set)
{
- WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX((m_transfers[i].m_flags & flag) == 0, "transfer #" << i << " already has flag " << flag << ": " << m_transfers[i].m_flags << ", transfer info:" << ENDL << epee::serialization::store_t_to_json(m_transfers[i]));
+ WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX((m_transfers.at(i).m_flags & flag) == 0, "transfer #" << i << " already has flag " << flag << ": " << m_transfers.at(i).m_flags << ", transfer info:" << ENDL << epee::serialization::store_t_to_json(m_transfers.at(i)));
}
}
for (uint64_t i : selected_transfers)
{
- uint32_t flags_before = m_transfers[i].m_flags;
- m_transfers[i].m_flags |= flag;
- WLT_LOG_L1("marking transfer #" << std::setfill('0') << std::right << std::setw(3) << i << " with flag " << flag << " : " << flags_before << " -> " << m_transfers[i].m_flags <<
+ uint32_t flags_before = m_transfers.at(i).m_flags;
+ m_transfers.at(i).m_flags |= flag;
+ WLT_LOG_L1("marking transfer #" << std::setfill('0') << std::right << std::setw(3) << i << " with flag " << flag << " : " << flags_before << " -> " << m_transfers.at(i).m_flags <<
(reason.empty() ? "" : ", reason: ") << reason);
}
}
@@ -7055,14 +7222,15 @@ void wallet2::clear_transfers_from_flag(const std::vector& selected_tr
TRY_ENTRY();
for (uint64_t i : selected_transfers)
{
- if (i >= m_transfers.size())
- {
- WLT_LOG_ERROR("INTERNAL ERROR: i: " << i << " >= m_transfers.size() : " << m_transfers.size());
- continue;
- }
- uint32_t flags_before = m_transfers[i].m_flags;
- m_transfers[i].m_flags &= ~flag;
- WLT_LOG_L1("clearing transfer #" << std::setfill('0') << std::right << std::setw(3) << i << " from flag " << flag << " : " << flags_before << " -> " << m_transfers[i].m_flags <<
+ //if (i >= m_transfers.size())
+ //{
+ // WLT_LOG_ERROR("INTERNAL ERROR: i: " << i << " >= m_transfers.size() : " << m_transfers.size());
+ // continue;
+ //}
+ auto& tr_entry = m_transfers.at(i);
+ uint32_t flags_before = tr_entry.m_flags;
+ tr_entry.m_flags &= ~flag;
+ WLT_LOG_L1("clearing transfer #" << std::setfill('0') << std::right << std::setw(3) << i << " from flag " << flag << " : " << flags_before << " -> " << tr_entry.m_flags <<
(reason.empty() ? "" : ", reason: ") << reason);
}
CATCH_ENTRY_NO_RETURN();
@@ -7091,79 +7259,79 @@ bool wallet2::extract_offers_from_transfer_entry(size_t i, std::unordered_map(ode) = od;
- //fill extra fields
- ode.tx_hash = m_transfer_history[i].tx_hash;
- ode.index_in_tx = 0; // TODO: handle multiple offers in tx, now only one per tx is supported
- ode.timestamp = m_transfer_history[i].timestamp;
- ode.fee = m_transfer_history[i].fee;
- ode.stopped = false;
+ WLT_LOG_ERROR("Transaction history entry " << i << " market as type " << m_transfer_history[i].tx_type << " but get_type_in_variant_container returned false for bc_services::offer_details");
break;
}
- case GUI_TX_TYPE_UPDATE_OFFER:
+ crypto::hash h = null_hash;
+ h = m_transfer_history[i].tx_hash;
+ bc_services::offer_details_ex& ode = offers_local[h];
+ ode = AUTO_VAL_INIT(bc_services::offer_details_ex());
+ static_cast(ode) = od;
+ //fill extra fields
+ ode.tx_hash = m_transfer_history[i].tx_hash;
+ ode.index_in_tx = 0; // TODO: handle multiple offers in tx, now only one per tx is supported
+ ode.timestamp = m_transfer_history[i].timestamp;
+ ode.fee = m_transfer_history[i].fee;
+ ode.stopped = false;
+ break;
+ }
+ case GUI_TX_TYPE_UPDATE_OFFER:
+ {
+ bc_services::update_offer uo;
+ if (!get_type_in_variant_container(m_transfer_history[i].marketplace_entries, uo))
{
- bc_services::update_offer uo;
- if (!get_type_in_variant_container(m_transfer_history[i].marketplace_entries, uo))
- {
- WLT_LOG_ERROR("Transaction history entry " << i << " market as type " << m_transfer_history[i].tx_type << " but get_type_in_variant_container returned false for update_offer");
- break;
- }
- crypto::hash h = null_hash;
- h = m_transfer_history[i].tx_hash;
- bc_services::offer_details_ex& ode = offers_local[h];
- ode = AUTO_VAL_INIT(bc_services::offer_details_ex());
- static_cast(ode) = uo.of;
- //fill extra fields
- ode.tx_hash = m_transfer_history[i].tx_hash;
- ode.index_in_tx = 0;
- ode.fee = m_transfer_history[i].fee;
- ode.stopped = false;
- ode.tx_original_hash = uo.tx_id;
- //remove old transaction
- crypto::hash h_old = uo.tx_id;
- auto it = offers_local.find(h_old);
- if (it == offers_local.end())
- {
- WLT_LOG_L3("Unable to find original tx record " << h_old << " in update offer " << h);
- break;
- }
- //keep original timestamp
- ode.timestamp = it->second.timestamp;
- offers_local.erase(it);
+ WLT_LOG_ERROR("Transaction history entry " << i << " market as type " << m_transfer_history[i].tx_type << " but get_type_in_variant_container returned false for update_offer");
break;
}
- case GUI_TX_TYPE_CANCEL_OFFER:
+ crypto::hash h = null_hash;
+ h = m_transfer_history[i].tx_hash;
+ bc_services::offer_details_ex& ode = offers_local[h];
+ ode = AUTO_VAL_INIT(bc_services::offer_details_ex());
+ static_cast(ode) = uo.of;
+ //fill extra fields
+ ode.tx_hash = m_transfer_history[i].tx_hash;
+ ode.index_in_tx = 0;
+ ode.fee = m_transfer_history[i].fee;
+ ode.stopped = false;
+ ode.tx_original_hash = uo.tx_id;
+ //remove old transaction
+ crypto::hash h_old = uo.tx_id;
+ auto it = offers_local.find(h_old);
+ if (it == offers_local.end())
+ {
+ WLT_LOG_L3("Unable to find original tx record " << h_old << " in update offer " << h);
+ break;
+ }
+ //keep original timestamp
+ ode.timestamp = it->second.timestamp;
+ offers_local.erase(it);
+ break;
+ }
+ case GUI_TX_TYPE_CANCEL_OFFER:
+ {
+ bc_services::cancel_offer co;
+ if (!get_type_in_variant_container(m_transfer_history[i].marketplace_entries, co))
+ {
+ WLT_LOG_ERROR("Transaction history entry " << i << " market as type " << m_transfer_history[i].tx_type << " but get_type_in_variant_container returned false for cancel_offer");
+ break;
+ }
+ crypto::hash h = co.tx_id;
+ auto it = offers_local.find(h);
+ if (it == offers_local.end())
{
- bc_services::cancel_offer co;
- if (!get_type_in_variant_container(m_transfer_history[i].marketplace_entries, co))
- {
- WLT_LOG_ERROR("Transaction history entry " << i << " market as type " << m_transfer_history[i].tx_type << " but get_type_in_variant_container returned false for cancel_offer");
- break;
- }
- crypto::hash h = co.tx_id;
- auto it = offers_local.find(h);
- if (it == offers_local.end())
- {
WLT_LOG_L3("Unable to find original tx record " << h << " in cancel offer " << h);
break;
- }
- offers_local.erase(it);
-
}
- default:
- ;
+ offers_local.erase(it);
+
+ }
+ default:
+ ;
}
return true;
@@ -7217,12 +7385,12 @@ bool wallet2::expand_selection_with_zc_input(assets_selection_context& needed_mo
{
for (auto it_in_amount = it->second.begin(); it_in_amount != it->second.end(); it_in_amount++)
{
- if (!m_transfers[*it_in_amount].is_zc())
+ if (!m_transfers.at(*it_in_amount).is_zc())
{
continue;
}
- if (is_transfer_ready_to_go(m_transfers[*it->second.begin()], fake_outputs_count))
+ if (is_transfer_ready_to_go(m_transfers.at(*it->second.begin()), fake_outputs_count))
{
asset_needed_money_item.found_amount += it->first;
selected_indexes.push_back(*it_in_amount);
@@ -7243,7 +7411,7 @@ bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money
{
for (auto& item : needed_money_map)
{
- if(item.second.needed_amount == 0)
+ if (item.second.needed_amount == 0)
continue;
const crypto::public_key asset_id = item.first;
@@ -7262,7 +7430,7 @@ bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money
bool found_zc_input = false;
for (auto i : selected_indexes)
{
- if (m_transfers[i].is_zc())
+ if (m_transfers.at(i).is_zc())
{
found_zc_input = true;
break;
@@ -7294,15 +7462,15 @@ uint64_t wallet2::select_indices_for_transfer(std::vector& selected_in
WLT_CHECK_AND_ASSERT_MES(it->second.size(), 0, "internal error: empty found_free_amounts map");
}
uint64_t fake_outputs_count = fake_outputs_count_;
- if (!this->is_auditable() && m_transfers[*it->second.begin()].is_zc())
+ if (!this->is_auditable() && m_transfers.at(*it->second.begin()).is_zc())
{
fake_outputs_count = m_core_runtime_config.hf4_minimum_mixins;
}
- if (is_transfer_ready_to_go(m_transfers[*it->second.begin()], fake_outputs_count))
+ if (is_transfer_ready_to_go(m_transfers.at(*it->second.begin()), fake_outputs_count))
{
found_money += it->first;
selected_indexes.push_back(*it->second.begin());
- WLT_LOG_L2("Selected index: " << *it->second.begin() << ", transfer_details: " << ENDL << epee::serialization::store_t_to_json(m_transfers[*it->second.begin()]));
+ WLT_LOG_L2("Selected index: " << *it->second.begin() << ", transfer_details: " << ENDL << epee::serialization::store_t_to_json(m_transfers.at(*it->second.begin())));
selected_amounts_str += (selected_amounts_str.empty() ? "" : "+") + print_money_brief(it->first, decimal_point);
++outputs_found;
}
@@ -7311,7 +7479,7 @@ uint64_t wallet2::select_indices_for_transfer(std::vector& selected_in
found_free_amounts.erase(it);
}
-
+
WLT_LOG_GREEN("Found " << print_money_brief(found_money, decimal_point) << " as " << outputs_found << " out(s): " << selected_amounts_str << ", found_free_amounts.size()=" << found_free_amounts.size() <<
(asset_id == native_coin_asset_id ? std::string() : std::string(", asset_id: ") + crypto::pod_to_hex(asset_id)), LOG_LEVEL_0);
return found_money;
@@ -7331,7 +7499,7 @@ bool wallet2::is_transfer_able_to_go(const transfer_details& td, uint64_t fake_o
if (!td.is_spendable())
return false;
- const tx_out_v &out_v = td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index];
+ const tx_out_v& out_v = td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index];
uint8_t mix_attr = CURRENCY_TO_KEY_OUT_RELAXED;
if (get_mix_attr_from_tx_out_v(out_v, mix_attr))
@@ -7342,11 +7510,11 @@ bool wallet2::is_transfer_able_to_go(const transfer_details& td, uint64_t fake_o
VARIANT_SWITCH_BEGIN(out_v);
VARIANT_CASE_CONST(tx_out_bare, o);
- if (o.target.type() == typeid(txout_htlc))
- {
- if (fake_outputs_count != 0)
- return false;
- }
+ if (o.target.type() == typeid(txout_htlc))
+ {
+ if (fake_outputs_count != 0)
+ return false;
+ }
VARIANT_SWITCH_END();
return true;
@@ -7359,9 +7527,10 @@ bool wallet2::prepare_free_transfers_cache(uint64_t fake_outputs_count)
if (!m_found_free_amounts.size() || fake_outputs_count != m_fake_outputs_count)
{
m_found_free_amounts.clear();
- for (size_t i = 0; i < m_transfers.size(); ++i)
+ for (const auto& tr : m_transfers)
{
- const transfer_details& td = m_transfers[i];
+ uint64_t i = tr.first;
+ const transfer_details& td = tr.second;
uint64_t fake_outputs_count_local = fake_outputs_count;
if (td.m_zc_info_ptr)
{
@@ -7386,7 +7555,7 @@ void wallet2::add_transfers_to_transfers_cache(const std::vector& inde
{
//@#@
for (auto i : indexs)
- add_transfer_to_transfers_cache(m_transfers[i].amount(), i, m_transfers[i].get_asset_id());
+ add_transfer_to_transfers_cache(m_transfers.at(i).amount(), i, m_transfers.at(i).get_asset_id());
}
//----------------------------------------------------------------------------------------------------
void wallet2::add_transfer_to_transfers_cache(uint64_t amount, uint64_t index, const crypto::public_key& asset_id /* = currency::native_coin_asset_id */)
@@ -7400,10 +7569,10 @@ bool wallet2::select_transfers(assets_selection_context& needed_money_map, size_
return select_indices_for_transfer(needed_money_map, fake_outputs_count, selected_indicies);
}
//----------------------------------------------------------------------------------------------------
-void wallet2::add_sent_unconfirmed_tx(const currency::transaction& tx,
- const std::vector& recipients,
- const std::vector& selected_indicies,
- const std::vector& splitted_dsts)
+void wallet2::add_sent_unconfirmed_tx(const currency::transaction& tx,
+ const std::vector& recipients,
+ const std::vector& selected_indicies,
+ const std::vector& splitted_dsts)
{
PROFILE_FUNC("wallet2::add_sent_unconfirmed_tx");
process_transaction_context ptc(tx);
@@ -7412,7 +7581,7 @@ void wallet2::add_sent_unconfirmed_tx(const currency::transaction& tx,
ptc.remote_aliases.push_back(get_alias_for_address(addr));
handle_unconfirmed_tx(ptc);
- wallet_public::wallet_transfer_info& unconfirmed_wti = misc_utils::get_or_insert_value_initialized(m_unconfirmed_txs, currency::get_transaction_hash(tx));
+ wallet_public::wallet_transfer_info& unconfirmed_wti = misc_utils::get_or_insert_value_initialized(m_unconfirmed_txs, currency::get_transaction_hash(tx));
//override some info that might be missing
unconfirmed_wti.selected_indicies = selected_indicies;
}
@@ -7444,15 +7613,15 @@ std::vector wallet2::get_aliases_for_address(const std::string& add
}
//----------------------------------------------------------------------------------------------------
void wallet2::transfer(const std::vector& dsts, size_t fake_outputs_count,
- uint64_t unlock_time, uint64_t fee, const std::vector& extra,
- const std::vector& attachments,
+ uint64_t unlock_time, uint64_t fee, const std::vector& extra,
+ const std::vector& attachments,
currency::transaction& tx)
{
transfer(dsts, fake_outputs_count, unlock_time, fee, extra, attachments, get_current_split_strategy(), tx_dust_policy(DEFAULT_DUST_THRESHOLD), tx);
}
//----------------------------------------------------------------------------------------------------
void wallet2::transfer(const std::vector& dsts, size_t fake_outputs_count,
- uint64_t unlock_time, uint64_t fee, const std::vector& extra,
+ uint64_t unlock_time, uint64_t fee, const std::vector& extra,
const std::vector& attachments)
{
currency::transaction tx;
@@ -7480,7 +7649,7 @@ void wallet2::process_genesis_if_needed(const currency::block& genesis, const st
crypto::hash genesis_hash = get_block_hash(genesis);
if (get_blockchain_current_size() == 1 && m_chain.get_genesis() != genesis_hash)
- WLT_LOG_L0("Changing genesis block for wallet " << m_account.get_public_address_str() << ":" << ENDL << " " << m_chain.get_genesis() << " -> " << genesis_hash);
+ WLT_LOG_L0("Changing genesis block for wallet " << m_account.get_public_address_str() << ":" << ENDL << " " << m_chain.get_genesis() << " -> " << genesis_hash);
//m_blockchain.clear();
@@ -7527,16 +7696,16 @@ uint64_t wallet2::get_tx_expiration_median() const
WLT_LOG_ERROR("COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN failed, status: " << res.status);
return 0;
}
-
+
return res.expiration_median;
}
//----------------------------------------------------------------------------------------------------
void wallet2::print_source_entry(std::stringstream& output, const currency::tx_source_entry& src) const
{
std::stringstream ss;
- for(auto& el : src.outputs)
+ for (auto& el : src.outputs)
ss << el.out_reference << " ";
-
+
output << "amount: " << print_money_brief(src.amount, get_asset_decimal_point(src.asset_id)) << (src.is_zc() ? "" : " (bare)");
if (src.asset_id != currency::native_coin_asset_id)
@@ -7548,7 +7717,7 @@ void wallet2::print_source_entry(std::stringstream& output, const currency::tx_s
}
//----------------------------------------------------------------------------------------------------
-bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) const
+bool wallet2::get_tx_key(const crypto::hash& txid, crypto::secret_key& tx_key) const
{
const std::unordered_map::const_iterator i = m_tx_keys.find(txid);
if (i == m_tx_keys.end())
@@ -7569,16 +7738,16 @@ void wallet2::prepare_tx_destinations(const assets_selection_context& needed_mon
uint8_t tx_flags,
std::vector& final_destinations)
{
-
- /*
- let's account all processes assets, so if there are some destinations
- that haven't been present in needed_money_map we can add it to final destinations
- (could be in ionic swaps for example)
+
+ /*
+ let's account all processes assets, so if there are some destinations
+ that haven't been present in needed_money_map we can add it to final destinations
+ (could be in ionic swaps for example)
*/
std::unordered_set