forked from lthn/blockchain
Merge branch 'develop' into release
This commit is contained in:
commit
c24d165627
74 changed files with 4183 additions and 2549 deletions
|
|
@ -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")
|
||||
|
|
|
|||
26
README.md
26
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`
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
## Supporting project/donations
|
||||
|
||||
ZANO @dev<br />
|
||||
BTC bc1qpa8w8eaehlplfepmnzpd7v9j046899nktxnkxp<br />
|
||||
BCH qqgq078vww5exd9kt3frx6krdyznmp80hcygzlgqzd<br />
|
||||
ETH 0x206c52b78141498e74FF074301ea90888C40c178<br />
|
||||
XMR 45gp9WTobeB5Km3kLQgVmPJkvm9rSmg4gdyHheXqXijXYMjUY48kLgL7QEz5Ar8z9vQioQ68WYDKsQsjAEonSeFX4UeLSiX<br />
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2019, Zano Project
|
||||
// Copyright (c) 2019-2024, Zano Project
|
||||
// Copyright (c) 2019, anonimal <anonimal@zano.org>
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -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;}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<true>::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<true>::serialize(a, stg, hparent_section, pname);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#ifndef DISABLE_PFR_SERIALIZATION_SELFCHECK
|
||||
#include <boost/pfr.hpp>
|
||||
#endif
|
||||
#define BEGIN_BOOST_SERIALIZATION() template <class t_archive> void serialize(t_archive &_arch, const unsigned int ver) {
|
||||
|
||||
template<size_t A, size_t B> struct TAssertEquality {
|
||||
|
|
@ -26,6 +29,60 @@ template<size_t A, size_t B> 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<std::remove_reference<decltype(*this)>::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<bool IsSaving, typename destination_t>
|
||||
struct boost_transition_t {};
|
||||
|
||||
template<typename destination_t>
|
||||
struct boost_transition_t<true, destination_t>
|
||||
{
|
||||
template <typename archive, typename origin_type>
|
||||
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<typename destination_t>
|
||||
struct boost_transition_t<false, destination_t>
|
||||
{
|
||||
template <typename archive, typename origin_type>
|
||||
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<t_archive::is_saving::value, old_type>::chain_serialize(_arch, *this);return;}
|
||||
|
||||
#define BOOST_CHAIN_TRANSITION_IF_COND_TRUE(condition, old_type) if (condition) {boost_transition_t<t_archive::is_saving::value, old_type>::chain_serialize(_arch, *this);return;}
|
||||
|
||||
/*
|
||||
example of use:
|
||||
|
||||
|
|
|
|||
|
|
@ -313,5 +313,18 @@ namespace boost
|
|||
{
|
||||
a & reinterpret_cast<char (&)[sizeof(crypto::eth_signature)]>(x);
|
||||
}
|
||||
template <class Archive>
|
||||
inline void serialize(Archive& a, crypto::scalar_vec_t& x, const boost::serialization::version_type ver)
|
||||
{
|
||||
static_assert(sizeof(std::vector<crypto::scalar_t>) == sizeof(crypto::scalar_vec_t));
|
||||
a & static_cast<std::vector<crypto::scalar_t>&>(x);
|
||||
}
|
||||
template <class Archive, size_t N>
|
||||
inline void serialize(Archive& a, crypto::scalar_mat_t<N>& x, const boost::serialization::version_type ver)
|
||||
{
|
||||
static_assert(sizeof(std::vector<crypto::scalar_t>) == sizeof(crypto::scalar_mat_t<N>));
|
||||
a & static_cast<std::vector<crypto::scalar_t>&>(x);
|
||||
}
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
|
|
|||
|
|
@ -1083,7 +1083,6 @@ namespace crypto
|
|||
make_random();
|
||||
}
|
||||
|
||||
|
||||
}; // scalar_vec_t
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <string_tools.h>
|
||||
|
||||
|
||||
#ifdef USE_OPEN_SSL_FOR_ECDSA
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rand.h>
|
||||
#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<unsigned char> 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<unsigned char> private_key; // 32 bytes
|
||||
// std::vector<unsigned char> 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(...)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ namespace currency
|
|||
std::vector<unsigned char> 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<uint64_t*>(&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<uint64_t*>(&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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<asset_descriptor_with_id>& 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<asset_descriptor_base&>(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<asset_descriptor_base&>(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<uint64_t> 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)
|
||||
|
|
|
|||
|
|
@ -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<uint64_t>& 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();
|
||||
|
|
|
|||
|
|
@ -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<transaction> explicit_txs;
|
||||
fill_block_template_func_t *pcustom_fill_block_template_func;
|
||||
|
|
|
|||
|
|
@ -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<dummy> asset_descriptor_base_etc_fields;
|
||||
typedef boost::variant<crypto::public_key, crypto::eth_public_key> 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<crypto::eth_public_key> 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<asset_descriptor_base_etc_fields> 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<dummy> 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<crypto::public_key> 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<crypto::public_key> opt_amount_commitment; // + + + - (premultiplied by 1/8)
|
||||
boost::optional<crypto::public_key> opt_asset_id; // - + + +
|
||||
boost::optional<asset_descriptor_base> opt_descriptor; // + - - +
|
||||
boost::optional<uint64_t> opt_amount; // ? ? ? - (only for non-hidden supply)
|
||||
boost::optional<uint32_t> opt_asset_id_salt; // ? - - - (optional)
|
||||
std::vector<asset_descriptor_operation_etc_fields> 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");
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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<crypto::public_key> 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<typename asset_descriptor_operation_t>
|
||||
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<typename asset_descriptor_operation_t>
|
||||
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;
|
||||
}
|
||||
|
|
@ -222,16 +222,7 @@ namespace boost
|
|||
a & x.buff;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
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 <class Archive>
|
||||
inline void serialize(Archive &a, currency::keypair &kp, const boost::serialization::version_type ver)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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<tx_out_v>& 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<crypto::point_t> 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<asset_operation_proof>(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<const asset_operation_proof>(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<uint16_t> 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<asset_descriptor_operation>(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);
|
||||
|
|
|
|||
|
|
@ -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<tx_out_v>& 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 invocable_t>
|
||||
typename std::enable_if_t<std::is_invocable_v<invocable_t, std::ostream&>, 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<typename t_type>
|
||||
|
|
|
|||
|
|
@ -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<block>()),
|
||||
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<block>())
|
||||
, 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<uint32_t>();
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ namespace currency
|
|||
volatile uint32_t m_thread_index;
|
||||
volatile uint32_t m_threads_total;
|
||||
std::atomic<int32_t> m_pausers_count;
|
||||
std::atomic<bool> m_block_template_ready;
|
||||
epee::critical_section m_miners_count_lock;
|
||||
|
||||
std::list<boost::thread> m_threads;
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ namespace currency
|
|||
|
||||
r = process_type_in_variant_container_and_make_sure_its_unique<asset_descriptor_operation>(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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <transaction_hash>");
|
||||
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 <addr> [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<std::string>& args)
|
||||
{
|
||||
std::map<uint32_t, time_t> 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<std::string>& 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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 5c878005ace55484eafe2985d204cd51e90b203b
|
||||
Subproject commit 7cd0e5e54a0d692ea819b9653f60a1cd5512dc2b
|
||||
|
|
@ -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<uint32_t, time_t>& blocklist);
|
||||
typedef COMMAND_REQUEST_STAT_INFO_T<typename t_payload_net_handler::stat_info> COMMAND_REQUEST_STAT_INFO;
|
||||
private:
|
||||
|
||||
|
|
|
|||
|
|
@ -448,6 +448,13 @@ namespace nodetool
|
|||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
void node_server<t_payload_net_handler>::get_ip_block_list(std::map<uint32_t, time_t>& blocklist)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_blocked_ips_lock);
|
||||
blocklist = m_blocked_ips;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
bool node_server<t_payload_net_handler>::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);
|
||||
|
|
|
|||
|
|
@ -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<std::string>& 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<std::string>& 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<bool>(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<std::string
|
|||
|
||||
uint64_t spent_count = 0;
|
||||
uint64_t unspent_count = 0;
|
||||
for (const auto& td : transfers)
|
||||
for (const auto& tr : transfers)
|
||||
{
|
||||
const auto& td = tr.second;
|
||||
if (td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_SPENT)
|
||||
{
|
||||
++spent_count;
|
||||
|
|
@ -2088,6 +2096,13 @@ bool simple_wallet::deploy_new_asset(const std::vector<std::string> &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;
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace currency
|
|||
typedef std::vector<std::string> command_type;
|
||||
|
||||
simple_wallet();
|
||||
~simple_wallet();
|
||||
virtual ~simple_wallet();
|
||||
bool init(const boost::program_options::variables_map& vm);
|
||||
bool deinit();
|
||||
bool run();
|
||||
|
|
|
|||
|
|
@ -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 "]"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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<bool> initialized;
|
||||
std::atomic<bool> initialized = false;
|
||||
std::atomic<bool> postponed_run_wallet = false;
|
||||
std::atomic<bool> postponed_main_worked_started = false;
|
||||
|
||||
std::atomic<uint64_t> gjobs_counter;
|
||||
std::map<uint64_t, std::string> gjobs;
|
||||
|
|
@ -73,7 +78,6 @@ namespace plain_wallet
|
|||
std::shared_ptr<plain_wallet::plain_wallet_instance> ginstance_ptr;
|
||||
|
||||
|
||||
|
||||
typedef epee::json_rpc::response<epee::json_rpc::dummy_result, error> 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<plain_wallet_instance> 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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -50,6 +50,8 @@
|
|||
|
||||
#define WALLET_DEFAULT_TX_SPENDABLE_AGE CURRENCY_HF4_MANDATORY_MIN_COINAGE
|
||||
#define WALLET_POS_MINT_CHECK_HEIGHT_INTERVAL 1
|
||||
#define WALLET_CONCISE_MODE_MAX_REORG_BLOCKS CURRENCY_BLOCKS_PER_DAY * 7 //week
|
||||
#define WALLET_CONCISE_MODE_MOBILE_MAX_HISTORY_SIZE 500
|
||||
|
||||
|
||||
const uint64_t WALLET_MINIMUM_HEIGHT_UNSET_CONST = std::numeric_limits<uint64_t>::max();
|
||||
|
|
@ -134,9 +136,9 @@ namespace tools
|
|||
std::unordered_map<crypto::key_image, size_t> m_key_images;
|
||||
std::vector<wallet_public::wallet_transfer_info> m_transfer_history;
|
||||
std::unordered_map<crypto::hash, currency::transaction> m_unconfirmed_in_transfers;
|
||||
std::unordered_map<crypto::hash, tools::wallet_public::wallet_transfer_info> m_unconfirmed_txs;
|
||||
unconfirmed_txs_container m_unconfirmed_txs;
|
||||
std::unordered_set<crypto::hash> m_unconfirmed_multisig_transfers;
|
||||
std::unordered_map<crypto::hash, crypto::secret_key> m_tx_keys;
|
||||
tx_secrete_keys_container m_tx_keys;
|
||||
std::unordered_map<crypto::public_key, wallet_own_asset_context> m_own_asset_descriptors;
|
||||
std::unordered_map<crypto::public_key, currency::asset_descriptor_base> m_custom_assets; //assets that manually added by user
|
||||
mutable std::unordered_map<crypto::public_key, currency::asset_descriptor_base> m_whitelisted_assets; //assets that whitelisted
|
||||
|
|
@ -149,13 +151,14 @@ namespace tools
|
|||
uint64_t m_last_pow_block_h = 0;
|
||||
std::list<std::pair<uint64_t, wallet_event_t>> m_rollback_events;
|
||||
std::list<std::pair<uint64_t, uint64_t> > m_last_zc_global_indexs; // <height, last_zc_global_indexs>, biggest height comes in front
|
||||
|
||||
|
||||
//variables that not being serialized
|
||||
std::atomic<uint64_t> m_last_bc_timestamp = 0;
|
||||
uint64_t m_height_of_start_sync = 0;
|
||||
std::atomic<uint64_t> m_last_sync_percent = 0;
|
||||
mutable uint64_t m_current_wallet_file_size = 0;
|
||||
bool m_use_assets_whitelisting = true;
|
||||
bool m_use_assets_whitelisting = true;
|
||||
mutable std::optional<bool> m_has_bare_unspent_outputs; // recalculated each time the balance() is called
|
||||
|
||||
// variables that should be part of state data object but should not be stored during serialization
|
||||
|
|
@ -201,7 +204,17 @@ namespace tools
|
|||
a & m_chain;
|
||||
a & m_minimum_height;
|
||||
a & m_amount_gindex_to_transfer_id;
|
||||
a & m_transfers;
|
||||
if (ver <= 167)
|
||||
{
|
||||
std::deque<transfer_details> transfer_container_old;
|
||||
a& transfer_container_old;
|
||||
for (size_t i = 0; i != transfer_container_old.size(); i++){m_transfers[i] = transfer_container_old[i];}
|
||||
}
|
||||
else
|
||||
{
|
||||
a& m_transfers;
|
||||
}
|
||||
|
||||
a & m_multisig_transfers;
|
||||
a & m_key_images;
|
||||
a & m_unconfirmed_txs;
|
||||
|
|
@ -234,7 +247,12 @@ namespace tools
|
|||
{
|
||||
//workaround for m_last_zc_global_indexs holding invalid index for last item
|
||||
m_last_zc_global_indexs.pop_front();
|
||||
}
|
||||
}
|
||||
if (ver <= 167)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -393,7 +411,7 @@ namespace tools
|
|||
//i_wallet2_callback* callback() const { return m_wcallback; }
|
||||
//void callback(i_wallet2_callback* callback) { m_callback = callback; }
|
||||
void callback(std::shared_ptr<i_wallet2_callback> callback) { m_wcallback = callback; m_do_rise_transfer = (callback != nullptr); }
|
||||
i_wallet2_callback* get_callback() { return m_wcallback.get(); }
|
||||
std::shared_ptr<i_wallet2_callback> get_callback() { return m_wcallback.lock(); }
|
||||
void set_do_rise_transfer(bool do_rise) { m_do_rise_transfer = do_rise; }
|
||||
|
||||
bool has_related_alias_entry_unconfirmed(const currency::transaction& tx);
|
||||
|
|
@ -422,13 +440,13 @@ namespace tools
|
|||
void deploy_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx, crypto::public_key& new_asset_id);
|
||||
void emit_asset(const crypto::public_key& asset_id, std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx);
|
||||
void update_asset(const crypto::public_key& asset_id, const currency::asset_descriptor_base new_descriptor, currency::transaction& result_tx);
|
||||
void burn_asset(const crypto::public_key& asset_id, uint64_t amount_to_burn, currency::transaction& result_tx);
|
||||
void burn_asset(const crypto::public_key& asset_id, uint64_t amount_to_burn, currency::transaction& result_tx, const std::vector<currency::tx_service_attachment>& service_entries = std::vector<currency::tx_service_attachment>(), const std::string& address_to_point = std::string(), uint64_t native_amount_to_point = 0);
|
||||
void transfer_asset_ownership(const crypto::public_key& asset_id, const currency::asset_owner_pub_key_v& new_owner_v, currency::transaction& result_tx);
|
||||
|
||||
void deploy_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector<currency::tx_destination_entry>& destinations, currency::finalized_tx& ft, crypto::public_key& new_asset_id);
|
||||
void emit_asset(const crypto::public_key& asset_id, const std::vector<currency::tx_destination_entry>& destinations, currency::finalized_tx& ft);
|
||||
void update_asset(const crypto::public_key& asset_id, const currency::asset_descriptor_base& new_descriptor, currency::finalized_tx& ft);
|
||||
void burn_asset(const crypto::public_key& asset_id, uint64_t amount_to_burn, currency::finalized_tx& ft);
|
||||
void burn_asset(const crypto::public_key& asset_id, uint64_t amount_to_burn, currency::finalized_tx& ft, const std::vector<currency::tx_service_attachment>& service_entries = std::vector<currency::tx_service_attachment>(), const std::string& address_to_point = std::string(), uint64_t native_amount_to_point = 0);
|
||||
void transfer_asset_ownership(const crypto::public_key& asset_id, const currency::asset_owner_pub_key_v& new_owner_v, currency::finalized_tx& ft);
|
||||
|
||||
bool daemon_get_asset_info(const crypto::public_key& asset_id, currency::asset_descriptor_base& adb);
|
||||
|
|
@ -565,10 +583,12 @@ namespace tools
|
|||
currency::transaction &escrow_template_tx);
|
||||
|
||||
bool check_connection();
|
||||
bool truncate_transfers_and_history(const std::list<size_t>& items_to_remove);
|
||||
bool truncate_wallet();
|
||||
|
||||
// PoS mining
|
||||
void do_pos_mining_prepare_entry(mining_context& cxt, size_t transfer_index);
|
||||
bool do_pos_mining_iteration(mining_context& cxt, size_t transfer_index, uint64_t ts);
|
||||
void do_pos_mining_prepare_entry(mining_context& cxt, const transfer_details& td);
|
||||
bool do_pos_mining_iteration(mining_context& cxt, uint64_t ts);
|
||||
template<typename idle_condition_cb_t> //do refresh as external callback
|
||||
bool scan_pos(mining_context& cxt, std::atomic<bool>& stop, idle_condition_cb_t idle_condition_cb, const currency::core_runtime_config &runtime_config);
|
||||
bool fill_mining_context(mining_context& ctx);
|
||||
|
|
@ -732,6 +752,9 @@ namespace tools
|
|||
bool accept_ionic_swap_proposal(const std::string& raw_proposal, currency::transaction& result_tx);
|
||||
bool accept_ionic_swap_proposal(const wallet_public::ionic_swap_proposal& proposal, currency::transaction& result_tx);
|
||||
|
||||
void fill_ado_version_based_onhardfork(currency::asset_descriptor_operation& asset_reg_info);
|
||||
void fill_adb_version_based_onhardfork(currency::asset_descriptor_base& asset_base);
|
||||
|
||||
// Signing and auth
|
||||
bool sign_buffer(const std::string& buff, crypto::signature& sig);
|
||||
bool validate_sign(const std::string& buff, const crypto::signature& sig, const crypto::public_key& pkey);
|
||||
|
|
@ -740,6 +763,9 @@ namespace tools
|
|||
bool is_in_hardfork_zone(uint64_t hardfork_index) const;
|
||||
//performance inefficient call, suitable only for rare ocasions or super lazy developers
|
||||
bool proxy_to_daemon(const std::string& uri, const std::string& body, int& response_code, std::string& response_body);
|
||||
void set_concise_mode(bool enabled) { m_concise_mode = enabled; }
|
||||
void set_concise_mode_reorg_max_reorg_blocks(uint64_t max_blocks) { m_wallet_concise_mode_max_reorg_blocks = max_blocks; }
|
||||
void set_concise_mode_truncate_history(uint64_t max_entries) { m_truncate_history_max_entries = max_entries; }
|
||||
|
||||
construct_tx_param get_default_construct_tx_param();
|
||||
|
||||
|
|
@ -774,7 +800,7 @@ private:
|
|||
bool on_idle();
|
||||
void unserialize_block_complete_entry(const currency::COMMAND_RPC_GET_BLOCKS_FAST::response& serialized,
|
||||
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& unserialized);
|
||||
void pull_blocks(size_t& blocks_added, std::atomic<bool>& stop);
|
||||
void pull_blocks(size_t& blocks_added, std::atomic<bool>& stop, bool& full_reset_needed);
|
||||
bool prepare_free_transfers_cache(uint64_t fake_outputs_count);
|
||||
bool select_transfers(assets_selection_context& needed_money_map, size_t fake_outputs_count, uint64_t dust, std::vector<uint64_t>& selected_indicies);
|
||||
void add_transfers_to_transfers_cache(const std::vector<uint64_t>& indexs);
|
||||
|
|
@ -795,7 +821,7 @@ private:
|
|||
void add_to_last_zc_global_indexs(uint64_t h, uint64_t last_zc_output_index);
|
||||
uint64_t get_actual_zc_global_index();
|
||||
void handle_pulled_blocks(size_t& blocks_added, std::atomic<bool>& stop,
|
||||
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& blocks);
|
||||
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& blocks, bool& full_reset_needed);
|
||||
std::string get_alias_for_address(const std::string& addr);
|
||||
std::vector<std::string> get_aliases_for_address(const std::string& addr);
|
||||
bool is_connected_to_net();
|
||||
|
|
@ -942,7 +968,7 @@ private:
|
|||
|
||||
std::atomic<bool> m_stop;
|
||||
std::shared_ptr<i_core_proxy> m_core_proxy;
|
||||
std::shared_ptr<i_wallet2_callback> m_wcallback;
|
||||
std::weak_ptr<i_wallet2_callback> m_wcallback;
|
||||
|
||||
|
||||
currency::core_runtime_config m_core_runtime_config;
|
||||
|
|
@ -958,8 +984,16 @@ private:
|
|||
std::string m_votes_config_path;
|
||||
tools::wallet_public::wallet_vote_config m_votes_config;
|
||||
|
||||
std::atomic<bool> m_concise_mode = true; //in this mode the wallet don't keep spent entries in m_transfers as well as m_recent_transfers longer then 100 entries
|
||||
uint64_t m_last_known_daemon_height = 0;
|
||||
|
||||
uint64_t m_wallet_concise_mode_max_reorg_blocks = WALLET_CONCISE_MODE_MAX_REORG_BLOCKS;
|
||||
uint64_t m_full_resync_requested_at_h = 0;
|
||||
uint64_t m_truncate_history_max_entries
|
||||
#ifdef MOBILE_WALLET_BUILD
|
||||
= WALLET_CONCISE_MODE_MOBILE_MAX_HISTORY_SIZE;
|
||||
#else
|
||||
= 0;
|
||||
#endif
|
||||
//this needed to access wallets state in coretests, for creating abnormal blocks and tranmsactions
|
||||
friend class test_generator;
|
||||
}; // class wallet2
|
||||
|
|
@ -1071,7 +1105,13 @@ namespace tools
|
|||
|
||||
if (tr_index != UINT64_MAX)
|
||||
{
|
||||
transfer_details& td = m_transfers[tr_index];
|
||||
auto it_tr = m_transfers.find(tr_index);
|
||||
if (it_tr == m_transfers.end())
|
||||
{
|
||||
throw tools::error::wallet_error_resync_needed();
|
||||
}
|
||||
transfer_details& td = it_tr->second;
|
||||
|
||||
ptc.total_balance_change[td.get_asset_id()] -= td.amount();
|
||||
if (td.is_native_coin())
|
||||
{
|
||||
|
|
@ -1121,9 +1161,9 @@ namespace tools
|
|||
ts_middle -= ts_middle % POS_SCAN_STEP;
|
||||
uint64_t ts_window = std::min(ts_middle - ts_from, ts_to - ts_middle);
|
||||
|
||||
for (size_t transfer_index = 0; transfer_index != m_transfers.size(); transfer_index++)
|
||||
for (auto it = m_transfers.begin(); it != m_transfers.end(); it++)//size_t transfer_index = 0; transfer_index != m_transfers.size(); transfer_index++)
|
||||
{
|
||||
auto& tr = m_transfers[transfer_index];
|
||||
auto& tr = it->second;
|
||||
|
||||
uint64_t stake_unlock_time = 0;
|
||||
if (!is_transfer_okay_for_pos(tr, cxt.zarcanum, stake_unlock_time))
|
||||
|
|
@ -1149,7 +1189,7 @@ namespace tools
|
|||
}
|
||||
};
|
||||
|
||||
do_pos_mining_prepare_entry(cxt, transfer_index);
|
||||
do_pos_mining_prepare_entry(cxt, tr);
|
||||
cxt.total_items_checked++;
|
||||
cxt.total_amount_checked += tr.amount();
|
||||
while(step <= ts_window)
|
||||
|
|
@ -1178,9 +1218,9 @@ namespace tools
|
|||
return false;
|
||||
|
||||
cxt.iterations_processed++;
|
||||
if (do_pos_mining_iteration(cxt, transfer_index, ts))
|
||||
if (do_pos_mining_iteration(cxt, ts))
|
||||
{
|
||||
cxt.index = transfer_index;
|
||||
cxt.index = it->first;
|
||||
cxt.stake_unlock_time = stake_unlock_time;
|
||||
cxt.status = API_RETURN_CODE_OK;
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@
|
|||
#define WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER uint32_t(1 << 3)
|
||||
#define WALLET_TRANSFER_DETAIL_FLAG_COLD_SIG_RESERVATION uint32_t(1 << 4) // transfer is reserved for cold-signing (unsigned tx was created and passed for signing)
|
||||
#define WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM uint32_t(1 << 5) // for htlc keeps info if this htlc belong as redeem or as refund
|
||||
#define WALLET_TRANSFER_DETAIL_FLAG_ASSET_OP_RESERVATION uint32_t(1 << 6) // transfer is reserved for an ongoing asset operation with external signing
|
||||
#define WALLET_TRANSFER_DETAIL_CONCISE_MODE_PRESERVE uint32_t(1 << 6) // do not truncate this output with CONCISE mode
|
||||
#define WALLET_TRANSFER_DETAIL_FLAG_ASSET_OP_RESERVATION uint32_t(1 << 7) // transfer is reserved for an ongoing asset operation with external signing
|
||||
|
||||
|
||||
|
||||
|
|
@ -228,6 +229,9 @@ namespace tools
|
|||
// misc
|
||||
std::string tx_meaning_for_logs; // used to correctly log things, e.g. "escrow" or "asset emission".
|
||||
uint32_t additional_transfer_flags_to_mark = 0;
|
||||
|
||||
//ado
|
||||
bool ado_sign_thirdparty = false;
|
||||
};
|
||||
|
||||
struct mode_separate_context
|
||||
|
|
@ -382,14 +386,16 @@ namespace tools
|
|||
return true;
|
||||
return false;
|
||||
}
|
||||
static inline uint64_t transfer_details_base_to_amount(const transfer_details_base& tdb)
|
||||
static inline bool transfer_details_base_to_amount(const transfer_details_base& tdb, uint64_t& val)
|
||||
{
|
||||
return tdb.amount();
|
||||
val = tdb.amount();
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
static inline std::string transfer_details_base_to_tx_hash(const transfer_details_base& tdb)
|
||||
static inline bool transfer_details_base_to_tx_hash(const transfer_details_base& tdb, std::string& val)
|
||||
{
|
||||
return epee::string_tools::pod_to_hex(currency::get_transaction_hash(tdb.m_ptx_wallet_info->m_tx));
|
||||
val = epee::string_tools::pod_to_hex(currency::get_transaction_hash(tdb.m_ptx_wallet_info->m_tx));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -511,12 +517,14 @@ namespace tools
|
|||
|
||||
typedef std::unordered_multimap<std::string, payment_details> payment_container;
|
||||
|
||||
typedef std::deque<transfer_details> transfer_container;
|
||||
typedef std::map<uint64_t, transfer_details> transfer_container; //typedef std::deque<transfer_details> transfer_container;
|
||||
typedef std::unordered_map<crypto::hash, transfer_details_base> multisig_transfer_container;
|
||||
typedef std::unordered_map<crypto::hash, tools::wallet_public::escrow_contract_details_basic> escrow_contracts_container;
|
||||
typedef std::map<uint64_t, std::set<size_t> > free_amounts_cache_type;
|
||||
typedef std::unordered_map<crypto::public_key, free_amounts_cache_type> free_assets_amounts_cache_type;
|
||||
typedef std::unordered_map<std::pair<uint64_t, uint64_t>, uint64_t> amount_gindex_to_transfer_id_container; // maps [amount; gindex] -> tid
|
||||
typedef std::unordered_map<crypto::hash, crypto::secret_key> tx_secrete_keys_container;
|
||||
typedef std::unordered_map<crypto::hash, tools::wallet_public::wallet_transfer_info> unconfirmed_txs_container;
|
||||
|
||||
}// namespace tools
|
||||
|
||||
|
|
|
|||
|
|
@ -321,6 +321,11 @@ namespace tools
|
|||
const currency::transaction m_tx;
|
||||
};
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
struct wallet_error_resync_needed : public std::exception
|
||||
{
|
||||
virtual const char* what() const noexcept override { return "wallet_error_resync_needed"; }
|
||||
};
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
struct tx_parse_error : public refresh_error
|
||||
{
|
||||
explicit tx_parse_error(std::string&& loc, const currency::blobdata& tx_blob)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Boolberry developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
|
@ -29,31 +29,36 @@ struct i_wallet_to_i_backend_adapter: public tools::i_wallet2_callback
|
|||
m_wallet_id(wallet_id)
|
||||
{}
|
||||
|
||||
virtual void on_new_block(uint64_t height, const currency::block& block) {
|
||||
virtual void on_new_block(uint64_t height, const currency::block& block) override
|
||||
{
|
||||
m_pbackend->on_new_block(m_wallet_id, height, block);
|
||||
}
|
||||
virtual void on_transfer2(const tools::wallet_public::wallet_transfer_info& wti, const std::list<tools::wallet_public::asset_balance_entry>& balances, uint64_t total_mined) {
|
||||
virtual void on_transfer2(const tools::wallet_public::wallet_transfer_info& wti, const std::list<tools::wallet_public::asset_balance_entry>& balances, uint64_t total_mined) override
|
||||
{
|
||||
m_pbackend->on_transfer2(m_wallet_id, wti, balances, total_mined);
|
||||
}
|
||||
virtual void on_pos_block_found(const currency::block& wti) {
|
||||
virtual void on_pos_block_found(const currency::block& wti) override
|
||||
{
|
||||
m_pbackend->on_pos_block_found(m_wallet_id, wti);
|
||||
}
|
||||
virtual void on_sync_progress(const uint64_t& progress) {
|
||||
virtual void on_sync_progress(const uint64_t& progress) override
|
||||
{
|
||||
m_pbackend->on_sync_progress(m_wallet_id, progress);
|
||||
}
|
||||
virtual void on_transfer_canceled(const tools::wallet_public::wallet_transfer_info& wti) {
|
||||
virtual void on_transfer_canceled(const tools::wallet_public::wallet_transfer_info& wti) override
|
||||
{
|
||||
m_pbackend->on_transfer_canceled(m_wallet_id, wti);
|
||||
}
|
||||
virtual void on_tor_status_change(const std::string& state)
|
||||
virtual void on_tor_status_change(const std::string& state) override
|
||||
{
|
||||
m_pbackend->on_tor_status_change(m_wallet_id, state);
|
||||
}
|
||||
|
||||
virtual void on_mw_get_wallets(std::vector<tools::wallet_public::wallet_entry_info>& wallets)
|
||||
virtual void on_mw_get_wallets(std::vector<tools::wallet_public::wallet_entry_info>& wallets) override
|
||||
{
|
||||
m_pbackend->on_mw_get_wallets(wallets);
|
||||
}
|
||||
virtual bool on_mw_select_wallet(uint64_t wallet_id)
|
||||
virtual bool on_mw_select_wallet(uint64_t wallet_id) override
|
||||
{
|
||||
return m_pbackend->on_mw_select_wallet(wallet_id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,7 +153,6 @@ namespace wallet_public
|
|||
std::vector<currency::tx_service_attachment> service_entries;
|
||||
std::vector<std::string> remote_addresses; //optional
|
||||
std::vector<std::string> remote_aliases; //optional, describe only if there only one remote address
|
||||
|
||||
std::vector<wallet_sub_transfer_info> subtransfers;
|
||||
|
||||
//not included in streaming serialization
|
||||
|
|
@ -191,6 +190,8 @@ namespace wallet_public
|
|||
KV_SERIALIZE(remote_addresses) DOC_DSCR("Remote addresses of this transfer(destination if it's outgoing transfer or sender if it's incoming transaction)") DOC_EXMP_AUTO(1, "ZxBvJDuQjMG9R2j4WnYUhBYNrwZPwuyXrC7FHdVmWqaESgowDvgfWtiXeNGu8Px9B24pkmjsA39fzSSiEQG1ekB225ZnrMTBp") DOC_END
|
||||
KV_SERIALIZE(remote_aliases) DOC_DSCR("Aliases for remot addresses, of discovered") DOC_EXMP_AUTO(1, "roger") DOC_END
|
||||
KV_SERIALIZE(subtransfers) DOC_DSCR("Essential part of transfer entry: amounts that been transfered in this transaction grouped by asset id") DOC_EXMP_AUTO(1) DOC_END
|
||||
|
||||
KV_SERIALIZE_EPHEMERAL_N(currency::asset_descriptor_operation, wallet_transfer_info_get_ado, "ado") DOC_DSCR("\"Asset Descriptor Operation\" if it was present in transaction") DOC_END
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
|
|
@ -277,6 +278,13 @@ namespace wallet_public
|
|||
subtransfers.back().is_income = true;
|
||||
return subtransfers.back().amount;
|
||||
}
|
||||
static inline bool wallet_transfer_info_get_ado(const wallet_transfer_info& tdb, currency::asset_descriptor_operation& val)
|
||||
{
|
||||
if (currency::get_type_in_variant_container(tdb.tx.extra, val))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct wallet_transfer_info_old : public wallet_transfer_info
|
||||
|
|
@ -291,14 +299,16 @@ namespace wallet_public
|
|||
KV_CHAIN_BASE(wallet_transfer_info)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
static uint64_t wallet_transfer_info_to_amount(const wallet_transfer_info_old& wtio)
|
||||
static bool wallet_transfer_info_to_amount(const wallet_transfer_info_old& wtio, uint64_t &val)
|
||||
{
|
||||
return wtio.get_native_amount();
|
||||
val = wtio.get_native_amount();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool wallet_transfer_info_to_is_income(const wallet_transfer_info_old& wtio)
|
||||
static bool wallet_transfer_info_to_is_income(const wallet_transfer_info_old& wtio, bool& val)
|
||||
{
|
||||
return wtio.get_native_is_income();
|
||||
val = wtio.get_native_is_income();
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1002,92 +1012,6 @@ namespace wallet_public
|
|||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_MAKETELEPOD
|
||||
{
|
||||
struct request
|
||||
{
|
||||
uint64_t amount;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amount)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string status; //"OK", "INSUFFICIENT_COINS", "INTERNAL_ERROR"
|
||||
telepod tpd;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status)
|
||||
KV_SERIALIZE(tpd)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct COMMAND_RPC_TELEPODSTATUS
|
||||
{
|
||||
struct request
|
||||
{
|
||||
telepod tpd;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(tpd)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string status; //"OK", "UNCONFIRMED", "BAD", "SPENT", "INTERNAL_ERROR"
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_CLONETELEPOD
|
||||
{
|
||||
struct request
|
||||
{
|
||||
telepod tpd;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(tpd)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string status;//"OK", "UNCONFIRMED", "BAD", "SPENT", "INTERNAL_ERROR:"
|
||||
telepod tpd;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status)
|
||||
KV_SERIALIZE(tpd)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_WITHDRAWTELEPOD
|
||||
{
|
||||
struct request
|
||||
{
|
||||
telepod tpd;
|
||||
std::string addr;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(tpd)
|
||||
KV_SERIALIZE(addr)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string status; //"OK", "UNCONFIRMED", "BAD", "SPENT", "INTERNAL_ERROR", "BAD_ADDRESS"
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct create_proposal_param
|
||||
{
|
||||
// uint64_t wallet_id;
|
||||
|
|
@ -2087,12 +2011,19 @@ namespace wallet_public
|
|||
|
||||
struct request
|
||||
{
|
||||
crypto::public_key asset_id;
|
||||
uint64_t burn_amount;
|
||||
crypto::public_key asset_id = currency::null_pkey;
|
||||
uint64_t burn_amount = 0;
|
||||
//optional params
|
||||
std::string point_tx_to_address;
|
||||
uint64_t native_amount = 0;
|
||||
std::vector<currency::tx_service_attachment> service_entries;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id) DOC_DSCR("Id of the asset to burn") DOC_EXMP("40fa6db923728b38962718c61b4dc3af1acaa1967479c73703e260dc3609c58d") DOC_END
|
||||
KV_SERIALIZE(burn_amount) DOC_DSCR("Amount to burn") DOC_EXMP(10000000) DOC_END
|
||||
KV_SERIALIZE(point_tx_to_address) DOC_DSCR("Optional, if we need this transaction to be seen by particular wallet") DOC_EXMP("ZxBvJDuQjMG9R2j4WnYUhBYNrwZPwuyXrC7FHdVmWqaESgowDvgfWtiXeNGu8Px9B24pkmjsA39fzSSiEQG1ekB225ZnrMTBp") DOC_END
|
||||
KV_SERIALIZE(native_amount) DOC_DSCR("Optional, if we need this transaction to be seen by particular wallet") DOC_EXMP(0) DOC_END
|
||||
KV_SERIALIZE(service_entries) DOC_DSCR("Optional, if we need to include service entries for burn transaction") DOC_EXMP_AUTO(1) DOC_END
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
|
@ -2114,8 +2045,8 @@ namespace wallet_public
|
|||
{
|
||||
currency::blobdata finalized_tx;
|
||||
currency::blobdata unsigned_tx;
|
||||
crypto::eth_signature eth_sig;
|
||||
crypto::hash expected_tx_id;
|
||||
crypto::eth_signature eth_sig; //TODO: add value initialization here
|
||||
crypto::hash expected_tx_id = currency::null_hash;
|
||||
bool unlock_transfers_on_fail = false;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
|
|
@ -2130,7 +2061,7 @@ namespace wallet_public
|
|||
struct response
|
||||
{
|
||||
std::string status;
|
||||
bool transfers_were_unlocked;
|
||||
bool transfers_were_unlocked = false;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status) DOC_DSCR("Status of the call") DOC_EXMP("OK") DOC_END
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ namespace tools
|
|||
return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init(m_port, m_bind_ip);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::auth_http_request(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response, connection_context& m_conn_context)
|
||||
bool wallet_rpc_server::auth_http_request(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response, connection_context& conn_context)
|
||||
{
|
||||
|
||||
auto it = std::find_if(query_info.m_header_info.m_etc_fields.begin(), query_info.m_header_info.m_etc_fields.end(), [](const auto& element)
|
||||
|
|
@ -252,7 +252,7 @@ namespace tools
|
|||
m_jwt_used_salts.add(salt, ticks_now + JWT_TOKEN_EXPIRATION_MAXIMUM);
|
||||
m_jwt_used_salts.remove_if_expiration_less_than(ticks_now);
|
||||
|
||||
LOG_PRINT_L0("JWT token OK");
|
||||
LOG_PRINT_L3("JWT token OK");
|
||||
return true;
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
|
|
@ -266,12 +266,13 @@ namespace tools
|
|||
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::handle_http_request(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response, connection_context& m_conn_context)
|
||||
bool wallet_rpc_server::handle_http_request(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response, epee::net_utils::connection_context_base& conn_context, bool& call_found, documentation& docs)
|
||||
{
|
||||
if (m_jwt_secret.size() && m_conn_context.m_connection_id != RPC_INTERNAL_UI_CONTEXT)
|
||||
if (m_jwt_secret.size() && conn_context.m_connection_id != RPC_INTERNAL_UI_CONTEXT)
|
||||
{
|
||||
if (!auth_http_request(query_info, response, m_conn_context))
|
||||
if (!auth_http_request(query_info, response, conn_context))
|
||||
{
|
||||
call_found = true;
|
||||
response.m_response_code = 401;
|
||||
response.m_response_comment = "Unauthorized";
|
||||
return true;
|
||||
|
|
@ -281,14 +282,13 @@ namespace tools
|
|||
response.m_response_code = 200;
|
||||
response.m_response_comment = "Ok";
|
||||
std::string reference_stub;
|
||||
bool call_found = false;
|
||||
if (m_deaf)
|
||||
{
|
||||
response.m_response_code = 500;
|
||||
response.m_response_comment = "Internal Server Error";
|
||||
return true;
|
||||
}
|
||||
if (!handle_http_request_map(query_info, response, m_conn_context, call_found) && response.m_response_code == 200)
|
||||
if (!handle_http_request_map(query_info, response, conn_context, call_found, docs) && response.m_response_code == 200)
|
||||
{
|
||||
response.m_response_code = 500;
|
||||
response.m_response_comment = "Internal Server Error";
|
||||
|
|
@ -1316,6 +1316,13 @@ namespace tools
|
|||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
||||
if (!currency::validate_asset_ticker_and_full_name(req.asset_descriptor))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT;
|
||||
er.message = "asset ticker or full_name is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<currency::tx_destination_entry> currency_destinations;
|
||||
rpc_destinations_to_currency_destinations(req.destinations, true, !req.do_not_split_destinations, currency_destinations);
|
||||
|
||||
|
|
@ -1388,7 +1395,7 @@ namespace tools
|
|||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
||||
currency::finalized_tx ft{};
|
||||
w.get_wallet()->burn_asset(req.asset_id, req.burn_amount, ft);
|
||||
w.get_wallet()->burn_asset(req.asset_id, req.burn_amount, ft, req.service_entries, req.point_tx_to_address, req.native_amount);
|
||||
res.tx_id = ft.tx_id;
|
||||
|
||||
return true;
|
||||
|
|
@ -1441,7 +1448,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_mw_get_wallets(const wallet_public::COMMAND_MW_GET_WALLETS::request& req, wallet_public::COMMAND_MW_GET_WALLETS::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
i_wallet2_callback* pcallback = w.get_wallet()->get_callback();
|
||||
std::shared_ptr<i_wallet2_callback> pcallback = w.get_wallet()->get_callback();
|
||||
if (!pcallback)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
|
|
@ -1456,7 +1463,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_mw_select_wallet(const wallet_public::COMMAND_MW_SELECT_WALLET::request& req, wallet_public::COMMAND_MW_SELECT_WALLET::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
i_wallet2_callback* pcallback = w.get_wallet()->get_callback();
|
||||
std::shared_ptr<i_wallet2_callback> pcallback = w.get_wallet()->get_callback();
|
||||
if (!pcallback)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,9 @@ namespace tools
|
|||
{
|
||||
wallet_provider_simple(std::shared_ptr<wallet2> wallet_ptr) : m_wallet_ptr(wallet_ptr)
|
||||
{}
|
||||
virtual std::shared_ptr<wallet2> get_wallet()
|
||||
|
||||
// interface i_wallet_provider
|
||||
virtual std::shared_ptr<wallet2> get_wallet() override
|
||||
{
|
||||
return m_wallet_ptr;
|
||||
}
|
||||
|
|
@ -88,7 +90,18 @@ namespace tools
|
|||
static void init_options(boost::program_options::options_description& desc);
|
||||
bool init(const boost::program_options::variables_map& vm);
|
||||
bool run(bool do_mint, bool offline_mode, const currency::account_public_address& miner_address);
|
||||
bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response, connection_context& m_conn_context);
|
||||
|
||||
virtual bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response_info,
|
||||
connection_context& conn_context)
|
||||
{
|
||||
bool call_found = false;
|
||||
return this->handle_http_request(query_info, response_info, conn_context, call_found, epee::net_utils::http::i_chain_handler::m_empty_documentation);
|
||||
}
|
||||
|
||||
// interface 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) override;
|
||||
|
||||
void set_jwt_secret(const std::string& jwt);
|
||||
const std::string& get_jwt_secret();
|
||||
|
||||
|
|
|
|||
|
|
@ -395,7 +395,13 @@ bool wallets_manager::start()
|
|||
CATCH_ENTRY_L0("main", false);
|
||||
}
|
||||
|
||||
|
||||
std::string wallets_manager::set_remote_node_url(const std::string& url)
|
||||
{
|
||||
if (m_rpc_proxy)
|
||||
m_rpc_proxy->set_connection_addr(url);
|
||||
|
||||
return API_RETURN_CODE_OK;
|
||||
}
|
||||
|
||||
bool wallets_manager::stop()
|
||||
{
|
||||
|
|
@ -1045,7 +1051,8 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st
|
|||
w->set_use_deffered_global_outputs(m_use_deffered_global_outputs);
|
||||
owr.wallet_id = m_wallet_id_counter++;
|
||||
|
||||
w->callback(std::shared_ptr<tools::i_wallet2_callback>(new i_wallet_to_i_backend_adapter(this, owr.wallet_id)));
|
||||
std::shared_ptr<tools::i_wallet2_callback> w_cb{new i_wallet_to_i_backend_adapter(this, owr.wallet_id)};
|
||||
w->callback(w_cb);
|
||||
if (m_remote_node_mode)
|
||||
{
|
||||
w->set_core_proxy(m_rpc_proxy);
|
||||
|
|
@ -1106,6 +1113,7 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st
|
|||
EXCLUSIVE_CRITICAL_REGION_LOCAL(m_wallets_lock);
|
||||
wallet_vs_options& wo = m_wallets[owr.wallet_id];
|
||||
**wo.w = w;
|
||||
wo.w_cb = w_cb;
|
||||
owr.wallet_file_size = w->get_wallet_file_size();
|
||||
get_wallet_info(wo, owr.wi);
|
||||
init_wallet_entry(wo, owr.wallet_id);
|
||||
|
|
@ -1921,7 +1929,10 @@ std::string wallets_manager::stop_pos_mining(uint64_t wallet_id)
|
|||
std::string wallets_manager::run_wallet(uint64_t wallet_id)
|
||||
{
|
||||
GET_WALLET_OPT_BY_ID(wallet_id, wo);
|
||||
wo.miner_thread = std::thread(boost::bind(&wallets_manager::wallet_vs_options::worker_func, &wo));
|
||||
if (!wo.major_stop && !wo.miner_thread.joinable())
|
||||
{
|
||||
wo.miner_thread = std::thread(boost::bind(&wallets_manager::wallet_vs_options::worker_func, &wo));
|
||||
}
|
||||
return API_RETURN_CODE_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public:
|
|||
{
|
||||
currency::core_runtime_config core_conf;
|
||||
epee::locked_object<std::shared_ptr<tools::wallet2>, wallet_lock_time_watching_policy> w;
|
||||
std::shared_ptr<tools::i_wallet2_callback> w_cb; // not using locked_object here, cuz w_cb is accessed only via it's wallet -- sowle
|
||||
typedef epee::locked_object<std::shared_ptr<tools::wallet2>, wallet_lock_time_watching_policy>::lock_shared_ptr wallet_lock_object;
|
||||
std::shared_ptr<tools::wallet_rpc_server> rpc_wrapper; //500 bytes of extra data, we can afford it, to have rpc-like invoke map
|
||||
std::atomic<bool> do_mining;
|
||||
|
|
@ -147,6 +148,7 @@ public:
|
|||
std::string get_tx_pool_info(currency::COMMAND_RPC_GET_POOL_INFO::response& res);
|
||||
std::string export_wallet_history(const view::export_wallet_info& ewi);
|
||||
std::string setup_wallet_rpc(const std::string& jwt_secret);
|
||||
std::string set_remote_node_url(const std::string& url);
|
||||
|
||||
#ifndef MOBILE_WALLET_BUILD
|
||||
currency::core_rpc_server& get_rpc_server() { return m_rpc_server; }
|
||||
|
|
@ -206,10 +208,10 @@ private:
|
|||
virtual bool on_mw_select_wallet(uint64_t wallet_id) override;
|
||||
|
||||
//----- i_wallet_provider ------
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
virtual void lock() override;
|
||||
virtual void unlock() override;
|
||||
//#ifndef MOBILE_WALLET_BUILD
|
||||
virtual std::shared_ptr<tools::wallet2> get_wallet();
|
||||
virtual std::shared_ptr<tools::wallet2> get_wallet() override;
|
||||
//#endif
|
||||
//--------
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ bool atomic_base_test::generate(std::vector<test_event_entry>& events) const
|
|||
test_core_time::adjust(m_genesis_timestamp);
|
||||
|
||||
|
||||
epee::debug::get_set_enable_assert(true, true);
|
||||
//epee::debug::get_set_enable_assert(true, true);
|
||||
|
||||
currency::account_base genesis_acc;
|
||||
genesis_acc.generate();
|
||||
|
|
@ -68,7 +68,7 @@ bool atomic_base_test::generate(std::vector<test_event_entry>& events) const
|
|||
REWIND_BLOCKS_N(events, blk_0r, blk_0, m_mining_accunt, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
epee::debug::get_set_enable_assert(true, false);
|
||||
//epee::debug::get_set_enable_assert(true, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -78,8 +78,8 @@ bool atomic_base_test::generate(std::vector<test_event_entry>& events) const
|
|||
|
||||
bool atomic_simple_test::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
epee::debug::get_set_enable_assert(true, true);
|
||||
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler([&](){epee::debug::get_set_enable_assert(true, false); });
|
||||
//epee::debug::get_set_enable_assert(true, true);
|
||||
//misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler([&](){epee::debug::get_set_enable_assert(true, false); });
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -997,6 +997,8 @@ bool test_generator::init_test_wallet(const currency::account_base& account, con
|
|||
w->set_genesis(genesis_hash);
|
||||
w->set_core_proxy(m_wallet_test_core_proxy);
|
||||
w->set_disable_tor_relay(true);
|
||||
w->set_concise_mode(true);
|
||||
w->set_concise_mode_reorg_max_reorg_blocks(TESTS_CONCISE_MODE_REORG_MAX_REORG_BLOCK);
|
||||
|
||||
result = w;
|
||||
return true;
|
||||
|
|
@ -1113,7 +1115,7 @@ bool test_generator::construct_pow_block_with_alias_info_in_coinbase(const accou
|
|||
miner_tx.proofs.emplace_back(std::move(currency::zc_asset_surjection_proof{}));
|
||||
// range proofs
|
||||
currency::zc_outs_range_proof range_proofs{};
|
||||
r = generate_zc_outs_range_proof(tx_id, 0, tx_gen_context, miner_tx.vout, range_proofs);
|
||||
r = generate_zc_outs_range_proof(tx_id, tx_gen_context, miner_tx.vout, range_proofs);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to generate zc_outs_range_proof()");
|
||||
miner_tx.proofs.emplace_back(std::move(range_proofs));
|
||||
// balance proof
|
||||
|
|
@ -2225,12 +2227,13 @@ bool make_tx_multisig_to_key(const currency::transaction& source_tx,
|
|||
|
||||
bool estimate_wallet_balance_blocked_for_escrow(const tools::wallet2& w, uint64_t& result, bool substruct_change_from_result /* = true */)
|
||||
{
|
||||
std::deque<tools::transfer_details> transfers;
|
||||
tools::transfer_container transfers;
|
||||
w.get_transfers(transfers);
|
||||
|
||||
result = 0;
|
||||
for (const tools::transfer_details& td : transfers)
|
||||
for (const auto& tr : transfers)
|
||||
{
|
||||
const tools::transfer_details& td = tr.second;
|
||||
if (td.m_flags == (WALLET_TRANSFER_DETAIL_FLAG_BLOCKED | WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION))
|
||||
result += td.amount();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,10 @@
|
|||
|
||||
#define TESTS_DEFAULT_FEE ((uint64_t)TX_DEFAULT_FEE)
|
||||
#define MK_TEST_COINS(amount) (static_cast<uint64_t>(amount) * TX_DEFAULT_FEE)
|
||||
#define TESTS_POS_CONFIG_MIN_COINSTAKE_AGE 4
|
||||
#define TESTS_POS_CONFIG_POS_MINIMUM_HEIGH 4
|
||||
#define TESTS_POS_CONFIG_MIN_COINSTAKE_AGE 4
|
||||
#define TESTS_POS_CONFIG_POS_MINIMUM_HEIGH 4
|
||||
#define TESTS_CONCISE_MODE_REORG_MAX_REORG_BLOCK 5
|
||||
|
||||
|
||||
namespace concolor
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
@ -17,25 +17,26 @@
|
|||
template<typename t_callbacktype>
|
||||
inline bool mine_next_pow_block_in_playtime(const currency::account_public_address& miner_addr, currency::core& c, t_callbacktype modify_block_cb, currency::block* output = nullptr)
|
||||
{
|
||||
currency::block b = AUTO_VAL_INIT(b);
|
||||
currency::wide_difficulty_type diff;
|
||||
uint64_t height;
|
||||
currency::blobdata extra = AUTO_VAL_INIT(extra);
|
||||
bool r = c.get_block_template(b, miner_addr, miner_addr, diff, height, extra);
|
||||
currency::create_block_template_params cbtp{};
|
||||
cbtp.ignore_pow_ts_check = true;
|
||||
cbtp.miner_address = miner_addr;
|
||||
currency::create_block_template_response cbtr{};
|
||||
bool r = c.get_block_template(cbtp, cbtr);
|
||||
CHECK_AND_ASSERT_MES(r, false, "get_block_template failed");
|
||||
currency::block& b = cbtr.b;
|
||||
|
||||
// adjust block's timestamp to keep difficulty low
|
||||
currency::block last_block = AUTO_VAL_INIT(last_block);
|
||||
currency::block last_block{};
|
||||
c.get_blockchain_storage().get_top_block(last_block);
|
||||
b.timestamp = last_block.timestamp + DIFFICULTY_POW_TARGET;
|
||||
// keep global time up with blocks' timestamps
|
||||
test_core_time::adjust(b.timestamp);
|
||||
|
||||
modify_block_cb(b);
|
||||
r = currency::miner::find_nonce_for_given_block(b, diff, height);
|
||||
r = currency::miner::find_nonce_for_given_block(b, cbtr.diffic, cbtr.height);
|
||||
CHECK_AND_ASSERT_MES(r, false, "find_nonce_for_given_block failed");
|
||||
|
||||
currency::block_verification_context bvc = AUTO_VAL_INIT(bvc);
|
||||
currency::block_verification_context bvc{};
|
||||
c.handle_incoming_block(t_serializable_object_to_blob(b), bvc);
|
||||
CHECK_AND_NO_ASSERT_MES(!bvc.m_verification_failed && !bvc.m_marked_as_orphaned && !bvc.m_already_exists, false, "block verification context check failed");
|
||||
|
||||
|
|
@ -79,21 +80,23 @@ inline bool mine_next_pow_block_in_playtime_with_given_txs(const currency::accou
|
|||
static epee::critical_section s_locker;
|
||||
|
||||
CHECK_AND_ASSERT_MES((height == SIZE_MAX) == (prev_id == currency::null_hash), false, "invalid agruments: height and prev_id should be specified or not specified together");
|
||||
currency::block b = AUTO_VAL_INIT(b);
|
||||
currency::wide_difficulty_type diff;
|
||||
uint64_t height_from_template = 0;
|
||||
currency::blobdata extra = AUTO_VAL_INIT(extra);
|
||||
currency::pos_entry pe = AUTO_VAL_INIT(pe);
|
||||
currency::create_block_template_params cbtp{};
|
||||
cbtp.ignore_pow_ts_check = true;
|
||||
cbtp.miner_address = miner_addr;
|
||||
cbtp.pcustom_fill_block_template_func = loc_helper::fill_block_template_func;
|
||||
currency::create_block_template_response cbtr{};
|
||||
bool r = false;
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(s_locker);
|
||||
loc_helper::txs_accessor() = &txs;
|
||||
r = c.get_blockchain_storage().create_block_template(miner_addr, miner_addr, extra, false, pe, loc_helper::fill_block_template_func, b, diff, height_from_template);
|
||||
r = c.get_block_template(cbtp, cbtr);
|
||||
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(r, false, "get_block_template failed");
|
||||
currency::block& b = cbtr.b;
|
||||
|
||||
// adjust block's timestamp to keep difficulty low
|
||||
currency::block last_block = AUTO_VAL_INIT(last_block);
|
||||
currency::block last_block{};
|
||||
if (prev_id == currency::null_hash)
|
||||
r = c.get_blockchain_storage().get_top_block(last_block);
|
||||
else
|
||||
|
|
@ -109,17 +112,17 @@ inline bool mine_next_pow_block_in_playtime_with_given_txs(const currency::accou
|
|||
CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() > 0, false, "invalid miner_tx.vin");
|
||||
CHECKED_GET_SPECIFIC_VARIANT(b.miner_tx.vin[0], currency::txin_gen, in, false);
|
||||
in.height = height;
|
||||
set_tx_unlock_time(b.miner_tx, height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
set_tx_unlock_time(b.miner_tx, cbtr.height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
height = height_from_template;
|
||||
height = cbtr.height;
|
||||
}
|
||||
|
||||
r = currency::miner::find_nonce_for_given_block(b, diff, height);
|
||||
r = currency::miner::find_nonce_for_given_block(b, cbtr.diffic, cbtr.height);
|
||||
CHECK_AND_ASSERT_MES(r, false, "find_nonce_for_given_block failed");
|
||||
|
||||
currency::block_verification_context bvc = AUTO_VAL_INIT(bvc);
|
||||
currency::block_verification_context bvc{};
|
||||
for (auto& tx : txs)
|
||||
{
|
||||
crypto::hash tx_id = currency::get_transaction_hash(tx);
|
||||
|
|
@ -153,7 +156,7 @@ inline bool mine_next_pow_blocks_in_playtime_with_given_txs(const currency::acco
|
|||
std::vector<currency::transaction> txs_local = txs;
|
||||
|
||||
crypto::hash prev_id_internal = prev_id;
|
||||
currency::block prv_block = AUTO_VAL_INIT(prv_block);
|
||||
currency::block prv_block{};
|
||||
bool r = c.get_blockchain_storage().get_block_by_hash(prev_id, prv_block);
|
||||
CHECK_AND_ASSERT_MES(r, false, "block with id " << prev_id << " not found");
|
||||
|
||||
|
|
@ -172,7 +175,7 @@ inline bool mine_next_pow_blocks_in_playtime_with_given_txs(const currency::acco
|
|||
// NOTE: stake coins return back to the wallet, newly generated coins go to miner_address (by default they are the same destinations)
|
||||
inline bool mine_next_pos_block_in_playtime_with_wallet(tools::wallet2& w, const currency::account_public_address& miner_address, size_t& pos_entries_count)
|
||||
{
|
||||
tools::wallet2::mining_context ctx = AUTO_VAL_INIT(ctx);
|
||||
tools::wallet2::mining_context ctx{};
|
||||
w.fill_mining_context(ctx);
|
||||
if (!ctx.is_pos_allowed)
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1218,7 +1218,9 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(tx_expiration_time_and_chain_switching);
|
||||
GENERATE_AND_PLAY(tx_key_image_pool_conflict);
|
||||
//GENERATE_AND_PLAY_HF(tx_version_against_hardfork, "4-*");
|
||||
GENERATE_AND_PLAY_HF(tx_pool_semantic_validation, "4-*");
|
||||
/* To execute the check of bare balance (function "check_tx_bare_balance") we need to run the test "tx_pool_semantic_validation" on the HF 3. By default behaviour bare outputs are disallowed on
|
||||
the heights >= 10. */
|
||||
GENERATE_AND_PLAY_HF(tx_pool_semantic_validation, "3");
|
||||
|
||||
// Double spend
|
||||
GENERATE_AND_PLAY(gen_double_spend_in_tx<false>);
|
||||
|
|
@ -1297,8 +1299,10 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY_HF(eth_signed_asset_basics, "5-*"); // TODO: make HF4 version
|
||||
GENERATE_AND_PLAY_HF(eth_signed_asset_via_rpc, "5-*"); // TODO: make HF4 version
|
||||
//GENERATE_AND_PLAY_HF(asset_current_and_total_supplies_comparative_constraints, "4-*"); <-- temporary disabled, waiting for Stepan's fix -- sowle
|
||||
GENERATE_AND_PLAY_HF(several_asset_emit_burn_txs_in_pool, "5-*");
|
||||
|
||||
GENERATE_AND_PLAY_HF(pos_fuse_test, "4-*");
|
||||
GENERATE_AND_PLAY_HF(wallet_reorganize_and_trim_test, "4-*");
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ using namespace currency;
|
|||
|
||||
cumulative_difficulty_adjustment_test::cumulative_difficulty_adjustment_test()
|
||||
{
|
||||
epee::debug::get_set_enable_assert(true, true);
|
||||
//epee::debug::get_set_enable_assert(true, true);
|
||||
REGISTER_CALLBACK_METHOD(cumulative_difficulty_adjustment_test, configure_core);
|
||||
REGISTER_CALLBACK_METHOD(cumulative_difficulty_adjustment_test, configure_check_height1);
|
||||
REGISTER_CALLBACK_METHOD(cumulative_difficulty_adjustment_test, memorize_main_chain);
|
||||
|
|
@ -25,7 +25,7 @@ cumulative_difficulty_adjustment_test::cumulative_difficulty_adjustment_test()
|
|||
}
|
||||
cumulative_difficulty_adjustment_test::~cumulative_difficulty_adjustment_test()
|
||||
{
|
||||
epee::debug::get_set_enable_assert(true, false);
|
||||
//epee::debug::get_set_enable_assert(true, false);
|
||||
}
|
||||
#define FIRST_ALIAS_NAME "first"
|
||||
#define SECOND_ALIAS_NAME "second"
|
||||
|
|
|
|||
|
|
@ -317,7 +317,8 @@ bool escrow_altchain_meta_impl::c1(currency::core& c, size_t ev_index, const std
|
|||
alice_wlt->scan_tx_pool(stub);
|
||||
size_t blocks_fetched = 0;
|
||||
alice_wlt->refresh(blocks_fetched);
|
||||
CHECK_AND_ASSERT_MES(blocks_fetched == se.expected_blocks, false, "Alice got " << blocks_fetched << " after refresh, but " << se.expected_blocks << " is expected");
|
||||
//fetched blocks disabled since resync might happened on different situation and number of blocks_fetched might be unexpected
|
||||
//CHECK_AND_ASSERT_MES(blocks_fetched == se.expected_blocks, false, "Alice got " << blocks_fetched << " after refresh, but " << se.expected_blocks << " is expected");
|
||||
LOG_PRINT_GREEN("Alice's transfers:" << ENDL << alice_wlt->dump_trunsfers(), LOG_LEVEL_1);
|
||||
if (se.a_balance != UINT64_MAX)
|
||||
{
|
||||
|
|
@ -335,7 +336,8 @@ bool escrow_altchain_meta_impl::c1(currency::core& c, size_t ev_index, const std
|
|||
bob_wlt->scan_tx_pool(stub);
|
||||
blocks_fetched = 0;
|
||||
bob_wlt->refresh(blocks_fetched);
|
||||
CHECK_AND_ASSERT_MES(blocks_fetched == se.expected_blocks, false, "Bob got " << blocks_fetched << " after refresh, but " << se.expected_blocks << " is expected");
|
||||
//fetched blocks disabled since resync might happened on different situation and number of blocks_fetched might be unexpected
|
||||
//CHECK_AND_ASSERT_MES(blocks_fetched == se.expected_blocks, false, "Bob got " << blocks_fetched << " after refresh, but " << se.expected_blocks << " is expected");
|
||||
LOG_PRINT_GREEN("Bob's transfers:" << ENDL << bob_wlt->dump_trunsfers(), LOG_LEVEL_1);
|
||||
if (se.b_balance != UINT64_MAX)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ escrow_wallet_test::escrow_wallet_test()
|
|||
|
||||
bool escrow_wallet_test::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
epee::debug::get_set_enable_assert(true, true);
|
||||
//epee::debug::get_set_enable_assert(true, true);
|
||||
|
||||
currency::account_base genesis_acc;
|
||||
genesis_acc.generate();
|
||||
|
|
@ -47,7 +47,7 @@ bool escrow_wallet_test::generate(std::vector<test_event_entry>& events) const
|
|||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
||||
epee::debug::get_set_enable_assert(true, false);
|
||||
//epee::debug::get_set_enable_assert(true, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -272,8 +272,8 @@ bool escrow_wallet_test::exec_test_with_cancel_release_type(currency::core& c, c
|
|||
|
||||
bool escrow_wallet_test::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
epee::debug::get_set_enable_assert(true, true);
|
||||
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler([&](){epee::debug::get_set_enable_assert(true, false); });
|
||||
//epee::debug::get_set_enable_assert(true, true);
|
||||
//misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler([&](){epee::debug::get_set_enable_assert(true, false); });
|
||||
|
||||
bool r = exec_test_with_cancel_release_type(c, events);
|
||||
if (!r)
|
||||
|
|
@ -287,7 +287,7 @@ bool escrow_wallet_test::c1(currency::core& c, size_t ev_index, const std::vecto
|
|||
if (!r)
|
||||
return false;
|
||||
|
||||
epee::debug::get_set_enable_assert(true, false);
|
||||
//epee::debug::get_set_enable_assert(true, false);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -780,7 +780,7 @@ bool escrow_proposal_expiration::c1(currency::core& c, size_t ev_index, const st
|
|||
uint64_t alice_post_proposal_balance = alice_wlt->balance();
|
||||
uint64_t alice_post_proposal_balance_expected = alice_start_balance - TESTS_DEFAULT_FEE;
|
||||
CHECK_AND_ASSERT_MES(alice_post_proposal_balance == alice_post_proposal_balance_expected, false, "Incorrect alice_post_proposal_balance: " << print_money(alice_post_proposal_balance) << ", expected: " << print_money(alice_post_proposal_balance_expected));
|
||||
std::deque<tools::transfer_details> transfers;
|
||||
tools::transfer_container transfers;
|
||||
alice_wlt->get_transfers(transfers);
|
||||
CHECK_AND_ASSERT_MES(transfers.size() == 2 && (
|
||||
(transfers[0].is_spent() && (transfers[1].m_flags & (WALLET_TRANSFER_DETAIL_FLAG_BLOCKED | WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION))) ||
|
||||
|
|
@ -2283,7 +2283,7 @@ bool escrow_proposal_not_enough_money::c1(currency::core& c, size_t ev_index, co
|
|||
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "Alice", MK_TEST_COINS(30), 0, MK_TEST_COINS(30), 0, 0), false, "");
|
||||
|
||||
std::deque<tools::transfer_details> transfers;
|
||||
tools::transfer_container transfers;
|
||||
alice_wlt->get_transfers(transfers);
|
||||
CHECK_AND_ASSERT_MES(transfers.size() == 1, false, "Incorrect transfers size: " << transfers.size());
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ bool isolate_auditable_and_proof::generate(std::vector<test_event_entry>& events
|
|||
test_core_time::adjust(m_genesis_timestamp);
|
||||
|
||||
|
||||
epee::debug::get_set_enable_assert(true, true);
|
||||
//epee::debug::get_set_enable_assert(true, true);
|
||||
|
||||
currency::account_base genesis_acc;
|
||||
genesis_acc.generate();
|
||||
|
|
@ -47,7 +47,7 @@ bool isolate_auditable_and_proof::generate(std::vector<test_event_entry>& events
|
|||
REWIND_BLOCKS_N(events, blk_0r, blk_0, m_mining_accunt, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 15);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
epee::debug::get_set_enable_assert(true, false);
|
||||
//epee::debug::get_set_enable_assert(true, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -61,8 +61,8 @@ bool isolate_auditable_and_proof::configure_core(currency::core& c, size_t ev_in
|
|||
|
||||
bool isolate_auditable_and_proof::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
epee::debug::get_set_enable_assert(true, true);
|
||||
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler([&](){epee::debug::get_set_enable_assert(true, false); });
|
||||
//epee::debug::get_set_enable_assert(true, true);
|
||||
//misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler([&](){epee::debug::get_set_enable_assert(true, false); });
|
||||
|
||||
LOG_PRINT_MAGENTA("Mining Address: " << currency::get_account_address_as_str(m_mining_accunt.get_public_address()), LOG_LEVEL_0);
|
||||
|
||||
|
|
|
|||
|
|
@ -310,10 +310,19 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
//miner_wlt->refresh();
|
||||
|
||||
|
||||
|
||||
// check emit_asset() with modified 'current_supply'
|
||||
miner_wlt->get_debug_events_dispatcher().SUBSCIRBE_DEBUG_EVENT<wde_construct_tx_handle_asset_descriptor_operation_before_seal>([&](const wde_construct_tx_handle_asset_descriptor_operation_before_seal& o)
|
||||
{
|
||||
o.pado->descriptor.current_supply += 1000000;
|
||||
if(o.pado->version < ASSET_DESCRIPTOR_OPERATION_HF5_VER)
|
||||
{
|
||||
//hf4
|
||||
o.pado->opt_descriptor->current_supply += 1000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
*o.pado->opt_amount += 1000000;
|
||||
}
|
||||
});
|
||||
//test emit function but re-adjust current_supply to wrong amount
|
||||
r = false;
|
||||
|
|
@ -345,7 +354,15 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
|
||||
miner_wlt->get_debug_events_dispatcher().SUBSCIRBE_DEBUG_EVENT<wde_construct_tx_handle_asset_descriptor_operation_before_burn>([&](const wde_construct_tx_handle_asset_descriptor_operation_before_burn& o)
|
||||
{
|
||||
o.pado->descriptor.current_supply -= 1000000;
|
||||
if (o.pado->version < ASSET_DESCRIPTOR_OPERATION_HF5_VER)
|
||||
{
|
||||
//hf4
|
||||
o.pado->opt_descriptor->current_supply -= 1000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
*o.pado->opt_amount -= 1000000;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -407,6 +424,31 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//@#@ TODO: subject for refactoring: this fill_ado*/fill_adb* are copy/paste clones of wallet's, need to be implemented in one place at some point
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void fill_ado_version_based_onhardfork(currency::asset_descriptor_operation& asset_reg_info, size_t current_latest_hf)
|
||||
{
|
||||
if (current_latest_hf < ZANO_HARDFORK_05)
|
||||
{
|
||||
asset_reg_info.version = ASSET_DESCRIPTOR_OPERATION_HF4_VER;
|
||||
}
|
||||
else
|
||||
{
|
||||
asset_reg_info.version = ASSET_DESCRIPTOR_OPERATION_LAST_VER;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void fill_adb_version_based_onhardfork(currency::asset_descriptor_base& asset_base, size_t current_latest_hf)
|
||||
{
|
||||
if (current_latest_hf < ZANO_HARDFORK_05)
|
||||
{
|
||||
asset_base.version = ASSET_DESCRIPTOR_BASE_HF4_VER;
|
||||
}
|
||||
else
|
||||
{
|
||||
asset_base.version = ASSET_DESCRIPTOR_BASE_LAST_VER;
|
||||
}
|
||||
}
|
||||
|
||||
assets_and_explicit_native_coins_in_outs::assets_and_explicit_native_coins_in_outs()
|
||||
{
|
||||
|
|
@ -535,7 +577,7 @@ bool assets_and_explicit_native_coins_in_outs::c2_alice_deploys_asset(currency::
|
|||
// make sure Alice has two UTXO now
|
||||
tools::transfer_container transfers{};
|
||||
alice_wlt->get_transfers(transfers);
|
||||
size_t unspent_transfers = std::count_if(transfers.begin(), transfers.end(), [](const tools::transfer_details& tr){ return !tr.is_spent(); });
|
||||
size_t unspent_transfers = std::count_if(transfers.begin(), transfers.end(), [](const auto& tr){ return !tr.second.is_spent(); });
|
||||
CHECK_AND_ASSERT_MES(unspent_transfers == 2, false, "unexpected number of Alice's unspent transfers: " << unspent_transfers);
|
||||
|
||||
asset_descriptor_base adb{};
|
||||
|
|
@ -694,15 +736,15 @@ bool asset_depoyment_and_few_zc_utxos::c1(currency::core& c, size_t ev_index, co
|
|||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", m_alice_initial_balance, 0, m_alice_initial_balance, 0, 0), false, "");
|
||||
|
||||
// make sure Alice has correct UTXO wallet structure
|
||||
tools::transfer_container transfers{};
|
||||
tools::transfer_container transfers;
|
||||
alice_wlt->get_transfers(transfers);
|
||||
size_t zc_unspent_outs = 0, unspent_outs = 0;
|
||||
for(auto& td : transfers)
|
||||
{
|
||||
if (!td.is_spent())
|
||||
if (!td.second.is_spent())
|
||||
{
|
||||
++unspent_outs;
|
||||
if (td.is_zc())
|
||||
if (td.second.is_zc())
|
||||
++zc_unspent_outs;
|
||||
}
|
||||
}
|
||||
|
|
@ -858,7 +900,7 @@ bool asset_emission_and_unconfirmed_balance::c1(currency::core& c, size_t ev_ind
|
|||
|
||||
asset_descriptor_base adb{};
|
||||
adb.total_max_supply = UINT64_MAX;
|
||||
adb.full_name = "2**64";
|
||||
adb.full_name = "2 xx 64";
|
||||
adb.ticker = "2POWER64";
|
||||
|
||||
std::vector<currency::tx_destination_entry> destinations;
|
||||
|
|
@ -894,6 +936,7 @@ bool asset_emission_and_unconfirmed_balance::c1(currency::core& c, size_t ev_ind
|
|||
|
||||
asset_operation_and_hardfork_checks::asset_operation_and_hardfork_checks()
|
||||
{
|
||||
m_adb_hello.version = ASSET_DESCRIPTOR_BASE_HF4_VER;
|
||||
m_adb_hello.total_max_supply = 1'000'000'000'000'000'000;
|
||||
m_adb_hello.current_supply = 1'000'000'000'000'000'000;
|
||||
m_adb_hello.ticker = "HLO";
|
||||
|
|
@ -903,6 +946,7 @@ asset_operation_and_hardfork_checks::asset_operation_and_hardfork_checks()
|
|||
|
||||
m_ado_hello.operation_type = ASSET_DESCRIPTOR_OPERATION_REGISTER;
|
||||
m_ado_hello.opt_asset_id = currency::null_pkey;
|
||||
m_ado_hello.version = ASSET_DESCRIPTOR_OPERATION_HF4_VER;
|
||||
|
||||
m_adb_bye.total_max_supply = 1'000'000'000'000'000'000;
|
||||
m_adb_bye.current_supply = 1'000'000'000'000'000'000;
|
||||
|
|
@ -913,6 +957,7 @@ asset_operation_and_hardfork_checks::asset_operation_and_hardfork_checks()
|
|||
|
||||
m_ado_bye.operation_type = ASSET_DESCRIPTOR_OPERATION_REGISTER;
|
||||
m_ado_hello.opt_asset_id = currency::null_pkey;
|
||||
m_ado_hello.version = ASSET_DESCRIPTOR_OPERATION_HF4_VER;
|
||||
|
||||
REGISTER_CALLBACK_METHOD(asset_operation_and_hardfork_checks, c1);
|
||||
REGISTER_CALLBACK_METHOD(asset_operation_and_hardfork_checks, c2);
|
||||
|
|
@ -942,10 +987,10 @@ bool asset_operation_and_hardfork_checks::generate(
|
|||
alice.generate();
|
||||
|
||||
m_adb_hello.owner = alice.get_public_address().spend_public_key;
|
||||
m_ado_hello.descriptor = m_adb_hello;
|
||||
m_ado_hello.opt_descriptor = m_adb_hello;
|
||||
|
||||
m_adb_bye.owner = alice.get_public_address().spend_public_key;
|
||||
m_ado_bye.descriptor = m_adb_bye;
|
||||
m_ado_bye.opt_descriptor = m_adb_bye;
|
||||
|
||||
MAKE_GENESIS_BLOCK(events,
|
||||
blk_0,
|
||||
|
|
@ -1014,7 +1059,9 @@ bool asset_operation_and_hardfork_checks::generate(
|
|||
/* asset_id = */ currency::null_pkey);
|
||||
|
||||
tx_version = get_tx_version(get_block_height(blk_1r), m_hardforks);
|
||||
|
||||
size_t hf_n = m_hardforks.get_the_most_recent_hardfork_id_for_height(get_block_height(blk_1r));
|
||||
fill_ado_version_based_onhardfork(m_ado_hello, hf_n);
|
||||
fill_adb_version_based_onhardfork(*m_ado_hello.opt_descriptor, hf_n);
|
||||
success = construct_tx(alice.get_keys(),
|
||||
sources,
|
||||
destinations,
|
||||
|
|
@ -1061,6 +1108,9 @@ bool asset_operation_and_hardfork_checks::generate(
|
|||
tx_version = get_tx_version(get_block_height(blk_2r),
|
||||
m_hardforks);
|
||||
|
||||
hf_n = m_hardforks.get_the_most_recent_hardfork_id_for_height(get_block_height(blk_2r));
|
||||
fill_ado_version_based_onhardfork(m_ado_hello, hf_n);
|
||||
fill_adb_version_based_onhardfork(*m_ado_hello.opt_descriptor, hf_n);
|
||||
success = construct_tx(alice.get_keys(),
|
||||
sources,
|
||||
destinations,
|
||||
|
|
@ -1099,6 +1149,10 @@ bool asset_operation_and_hardfork_checks::generate(
|
|||
tx_version = get_tx_version(get_block_height(blk_2r),
|
||||
m_hardforks);
|
||||
|
||||
hf_n = m_hardforks.get_the_most_recent_hardfork_id_for_height(get_block_height(blk_2r));
|
||||
fill_ado_version_based_onhardfork(m_ado_bye, hf_n);
|
||||
fill_adb_version_based_onhardfork(*m_ado_bye.opt_descriptor, hf_n);
|
||||
|
||||
success = construct_tx(alice.get_keys(),
|
||||
sources,
|
||||
destinations,
|
||||
|
|
@ -1134,6 +1188,10 @@ bool asset_operation_and_hardfork_checks::generate(
|
|||
tx_version = get_tx_version(get_block_height(blk_2r),
|
||||
m_hardforks);
|
||||
|
||||
hf_n = m_hardforks.get_the_most_recent_hardfork_id_for_height(get_block_height(blk_2r));
|
||||
fill_ado_version_based_onhardfork(m_ado_bye, hf_n);
|
||||
fill_adb_version_based_onhardfork(*m_ado_bye.opt_descriptor, hf_n);
|
||||
|
||||
success = construct_tx(alice.get_keys(),
|
||||
sources,
|
||||
destinations,
|
||||
|
|
@ -1212,6 +1270,7 @@ bool asset_operation_and_hardfork_checks::c2(
|
|||
|
||||
asset_operation_in_consolidated_tx::asset_operation_in_consolidated_tx()
|
||||
{
|
||||
m_adb_alice_currency.version = ASSET_DESCRIPTOR_BASE_HF4_VER;
|
||||
m_adb_alice_currency.total_max_supply = 1'000'000'000'000'000'000;
|
||||
m_adb_alice_currency.current_supply = 1'000'000'000'000'000'000;
|
||||
m_adb_alice_currency.ticker = "ALC";
|
||||
|
|
@ -1221,6 +1280,7 @@ asset_operation_in_consolidated_tx::asset_operation_in_consolidated_tx()
|
|||
|
||||
m_ado_alice_currency.operation_type = ASSET_DESCRIPTOR_OPERATION_REGISTER;
|
||||
m_ado_alice_currency.opt_asset_id = currency::null_pkey;
|
||||
m_ado_alice_currency.version = ASSET_DESCRIPTOR_OPERATION_HF4_VER;
|
||||
|
||||
REGISTER_CALLBACK_METHOD(asset_operation_in_consolidated_tx, assert_balances);
|
||||
REGISTER_CALLBACK_METHOD(asset_operation_in_consolidated_tx, assert_alice_currency_not_registered);
|
||||
|
|
@ -1242,7 +1302,7 @@ bool asset_operation_in_consolidated_tx::generate(std::vector<test_event_entry>&
|
|||
m_accounts.push_back(alice);
|
||||
m_accounts.push_back(bob);
|
||||
m_adb_alice_currency.owner = m_accounts.at(ALICE_ACC_IDX).get_public_address().spend_public_key;
|
||||
m_ado_alice_currency.descriptor = m_adb_alice_currency;
|
||||
m_ado_alice_currency.opt_descriptor = m_adb_alice_currency;
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner, test_core_time::get_time());
|
||||
DO_CALLBACK(events, "configure_core");
|
||||
|
|
@ -1288,6 +1348,11 @@ bool asset_operation_in_consolidated_tx::generate(std::vector<test_event_entry>&
|
|||
destinations.emplace_back(MK_TEST_COINS(/* 10 - 5 - 0 = */ 5), bob.get_public_address());
|
||||
destinations.emplace_back(m_adb_alice_currency.current_supply, alice.get_public_address(), null_pkey);
|
||||
tx_version = get_tx_version(get_block_height(blk_2r), m_hardforks);
|
||||
size_t hf_n = m_hardforks.get_the_most_recent_hardfork_id_for_height(get_block_height(blk_2r));
|
||||
fill_ado_version_based_onhardfork(m_ado_alice_currency, hf_n);
|
||||
fill_adb_version_based_onhardfork(*m_ado_alice_currency.opt_descriptor, hf_n);
|
||||
|
||||
|
||||
success = construct_tx(bob.get_keys(), sources, destinations, { m_ado_alice_currency }, empty_attachment, tx_2, tx_version, one_time, 0, 0, 0, true, TX_FLAG_SIGNATURE_MODE_SEPARATE,
|
||||
/* fee = */ 0, context_tx_2);
|
||||
CHECK_AND_ASSERT_MES(success, false, "failed to construct transaction tx_2 on step 2");
|
||||
|
|
@ -1348,7 +1413,6 @@ bool eth_signed_asset_basics::generate(std::vector<test_event_entry>& events) co
|
|||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
|
||||
miner_acc.generate();
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
|
||||
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
|
||||
|
|
@ -1423,7 +1487,9 @@ bool eth_signed_asset_basics::c1(currency::core& c, size_t ev_index, const std::
|
|||
crypto::eth_signature eth_sig{};
|
||||
r = crypto::generate_eth_signature(ft.tx_id, eth_sk, eth_sig);
|
||||
CHECK_AND_ASSERT_MES(r, false, "generate_eth_signature failed");
|
||||
|
||||
r = crypto::verify_eth_signature(ft.tx_id, eth_pk, eth_sig);
|
||||
CHECK_AND_ASSERT_MES(r, false, "generate_eth_signature self validation failed");
|
||||
|
||||
transaction emit_tx{};
|
||||
bool transfers_unlocked = false;
|
||||
miner_wlt->submit_externally_signed_asset_tx(ft, eth_sig, true, emit_tx, transfers_unlocked);
|
||||
|
|
@ -1560,7 +1626,6 @@ bool eth_signed_asset_via_rpc::generate(std::vector<test_event_entry>& events) c
|
|||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
|
||||
account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc.generate(); bob_acc.set_createtime(ts);
|
||||
miner_acc.generate();
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
|
||||
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
|
||||
|
|
@ -1805,8 +1870,8 @@ bool eth_signed_asset_via_rpc::c1(currency::core& c, size_t ev_index, const std:
|
|||
CHECK_AND_ASSERT_EQ(pado->operation_type, ASSET_DESCRIPTOR_OPERATION_UPDATE);
|
||||
CHECK_AND_ASSERT_EQ(pado->opt_asset_id.has_value(), true);
|
||||
CHECK_AND_ASSERT_EQ(pado->opt_asset_id.get(), asset_id);
|
||||
CHECK_AND_ASSERT_EQ(pado->descriptor.owner_eth_pub_key.has_value(), true);
|
||||
CHECK_AND_ASSERT_EQ(pado->descriptor.owner_eth_pub_key.get(), eth_pk_2); // the most important condition for an ownership transfer
|
||||
CHECK_AND_ASSERT_EQ(pado->opt_descriptor->owner_eth_pub_key.has_value(), true);
|
||||
CHECK_AND_ASSERT_EQ(pado->opt_descriptor->owner_eth_pub_key.get(), eth_pk_2); // the most important condition for an ownership transfer
|
||||
// other fileds of pado->descriptor may also be checked here
|
||||
|
||||
//
|
||||
|
|
@ -2007,12 +2072,13 @@ bool asset_current_and_total_supplies_comparative_constraints::generate(std::vec
|
|||
m_accounts.push_back(miner);
|
||||
m_accounts.push_back(alice);
|
||||
m_adbs.at(asset_position::alpha).owner = m_adbs.at(asset_position::beta).owner = m_adbs.at(asset_position::gamma).owner = alice.get_public_address().spend_public_key;
|
||||
m_ados_register.at(asset_position::alpha).descriptor = m_adbs.at(asset_position::alpha);
|
||||
m_ados_register.at(asset_position::beta).descriptor = m_ado_emit.descriptor = m_adbs.at(asset_position::beta);
|
||||
m_ados_register.at(asset_position::gamma).descriptor = m_adbs.at(asset_position::gamma);
|
||||
CHECK_AND_ASSERT(m_ado_emit.descriptor.current_supply <= m_ado_emit.descriptor.total_max_supply, false);
|
||||
++m_ado_emit.descriptor.current_supply;
|
||||
CHECK_AND_ASSERT(m_ado_emit.descriptor.current_supply > m_ado_emit.descriptor.total_max_supply, false);
|
||||
m_ados_register.at(asset_position::alpha).opt_descriptor = m_adbs.at(asset_position::alpha);
|
||||
m_ados_register.at(asset_position::beta).opt_descriptor = m_ado_emit.opt_descriptor = m_adbs.at(asset_position::beta);
|
||||
m_ados_register.at(asset_position::gamma).opt_descriptor = m_adbs.at(asset_position::gamma);
|
||||
|
||||
CHECK_AND_ASSERT((*m_ado_emit.opt_descriptor).current_supply <= (*m_ado_emit.opt_descriptor).total_max_supply, false);
|
||||
++(m_ado_emit.opt_descriptor->current_supply);
|
||||
CHECK_AND_ASSERT(m_ado_emit.opt_descriptor->current_supply > m_ado_emit.opt_descriptor->total_max_supply, false);
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner, test_core_time::get_time());
|
||||
DO_CALLBACK(events, "configure_core");
|
||||
|
|
@ -2040,12 +2106,15 @@ bool asset_current_and_total_supplies_comparative_constraints::generate(std::vec
|
|||
std::vector<tx_destination_entry> destinations{};
|
||||
const auto& ado{m_ados_register.at(asset_position::gamma)};
|
||||
crypto::secret_key one_time{};
|
||||
size_t hf_n = m_hardforks.get_the_most_recent_hardfork_id_for_height(get_block_height(blk_1r));
|
||||
//fill_ado_version_based_onhardfork(ado, hf_n);
|
||||
//fill_adb_version_based_onhardfork(*ado.opt_descriptor, hf_n);
|
||||
|
||||
success = fill_tx_sources_and_destinations(events, top, alice.get_keys(), alice.get_public_address(), MK_TEST_COINS(2), TESTS_DEFAULT_FEE, 0, sources, destinations);
|
||||
CHECK_AND_ASSERT_EQ(success, true);
|
||||
destinations.emplace_back(ado.descriptor.current_supply, alice.get_public_address(), null_pkey);
|
||||
CHECK_AND_ASSERT_EQ(ado.descriptor.total_max_supply, 0);
|
||||
CHECK_AND_ASSERT_EQ(ado.descriptor.total_max_supply, ado.descriptor.current_supply);
|
||||
destinations.emplace_back(ado.opt_descriptor->current_supply, alice.get_public_address(), null_pkey);
|
||||
CHECK_AND_ASSERT_EQ(ado.opt_descriptor->total_max_supply, 0);
|
||||
CHECK_AND_ASSERT_EQ(ado.opt_descriptor->total_max_supply, ado.opt_descriptor->current_supply);
|
||||
success = construct_tx(alice.get_keys(), sources, destinations, {ado}, empty_attachment, tx_1, get_tx_version(get_block_height(top), m_hardforks), one_time, 0);
|
||||
CHECK_AND_ASSERT_EQ(success, true);
|
||||
}
|
||||
|
|
@ -2063,11 +2132,14 @@ bool asset_current_and_total_supplies_comparative_constraints::generate(std::vec
|
|||
std::vector<tx_destination_entry> destinations{};
|
||||
crypto::secret_key one_time{};
|
||||
const auto& ado{m_ados_register.at(asset_position::alpha)};
|
||||
size_t hf_n = m_hardforks.get_the_most_recent_hardfork_id_for_height(get_block_height(blk_2r));
|
||||
//fill_ado_version_based_onhardfork(ado, hf_n);
|
||||
//fill_adb_version_based_onhardfork(*ado.opt_descriptor, hf_n);
|
||||
|
||||
success = fill_tx_sources_and_destinations(events, top, alice.get_keys(), alice.get_public_address(), MK_TEST_COINS(2), TESTS_DEFAULT_FEE, 0, sources, destinations);
|
||||
CHECK_AND_ASSERT_EQ(success, true);
|
||||
destinations.emplace_back(ado.descriptor.current_supply, alice.get_public_address(), null_pkey);
|
||||
CHECK_AND_ASSERT_MES(ado.descriptor.current_supply > ado.descriptor.total_max_supply, false, "current_supply <= total_max_supply");
|
||||
destinations.emplace_back(ado.opt_descriptor->current_supply, alice.get_public_address(), null_pkey);
|
||||
CHECK_AND_ASSERT_MES(ado.opt_descriptor->current_supply > ado.opt_descriptor->total_max_supply, false, "current_supply <= total_max_supply");
|
||||
success = construct_tx(alice.get_keys(), sources, destinations, {ado}, empty_attachment, tx_2, get_tx_version(get_block_height(top), m_hardforks), one_time, 0);
|
||||
CHECK_AND_ASSERT_EQ(success, true);
|
||||
}
|
||||
|
|
@ -2085,11 +2157,14 @@ bool asset_current_and_total_supplies_comparative_constraints::generate(std::vec
|
|||
std::vector<tx_destination_entry> destinations{};
|
||||
crypto::secret_key one_time{};
|
||||
const auto& ado{m_ados_register.at(asset_position::beta)};
|
||||
size_t hf_n = m_hardforks.get_the_most_recent_hardfork_id_for_height(get_block_height(blk_2r));
|
||||
//fill_ado_version_based_onhardfork(ado, hf_n);
|
||||
//fill_adb_version_based_onhardfork(*ado.opt_descriptor, hf_n);
|
||||
|
||||
success = fill_tx_sources_and_destinations(events, top, alice.get_keys(), alice.get_public_address(), MK_TEST_COINS(2), TESTS_DEFAULT_FEE, 0, sources, destinations);
|
||||
CHECK_AND_ASSERT_EQ(success, true);
|
||||
destinations.emplace_back(ado.descriptor.current_supply, alice.get_public_address(), null_pkey);
|
||||
CHECK_AND_ASSERT(ado.descriptor.current_supply <= ado.descriptor.total_max_supply, false);
|
||||
destinations.emplace_back(ado.opt_descriptor->current_supply, alice.get_public_address(), null_pkey);
|
||||
CHECK_AND_ASSERT(ado.opt_descriptor->current_supply <= ado.opt_descriptor->total_max_supply, false);
|
||||
success = construct_tx(alice.get_keys(), sources, destinations, {ado}, empty_attachment, tx_3, get_tx_version(get_block_height(top), m_hardforks), one_time, 0);
|
||||
CHECK_AND_ASSERT_EQ(success, true);
|
||||
}
|
||||
|
|
@ -2108,7 +2183,7 @@ bool asset_current_and_total_supplies_comparative_constraints::generate(std::vec
|
|||
m_ado_emit.opt_asset_id = beta_asset_id;
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_GREATER(m_ado_emit.descriptor.current_supply, m_ado_emit.descriptor.total_max_supply);
|
||||
CHECK_AND_ASSERT_GREATER(m_ado_emit.opt_descriptor->current_supply, m_ado_emit.opt_descriptor->total_max_supply);
|
||||
// Alice emits asset BETA. The emission is performed through the wallet object. There is no emission, because .current_supply > .total_max_supply in the asset base descriptor.
|
||||
DO_CALLBACK(events, "emit_asset_beta_with_incorrect_supply");
|
||||
|
||||
|
|
@ -2123,18 +2198,25 @@ bool asset_current_and_total_supplies_comparative_constraints::generate(std::vec
|
|||
tx_source_entry source{};
|
||||
finalize_tx_param ftp{};
|
||||
finalized_tx ftx{};
|
||||
|
||||
size_t hf_n = m_hardforks.get_the_most_recent_hardfork_id_for_height(get_block_height(blk_3r));
|
||||
//fill_ado_version_based_onhardfork(ado_register, hf_n);
|
||||
//fill_adb_version_based_onhardfork(*ado_register.opt_descriptor, hf_n);
|
||||
|
||||
success = fill_tx_sources_and_destinations(events, top, alice.get_keys(), alice.get_public_address(), MK_TEST_COINS(2), TESTS_DEFAULT_FEE, 0, sources, destinations);
|
||||
CHECK_AND_ASSERT_EQ(success, true);
|
||||
CHECK_AND_ASSERT_GREATER(m_ado_emit.descriptor.current_supply, ado_register.descriptor.current_supply);
|
||||
destinations.emplace_back(m_ado_emit.descriptor.current_supply - ado_register.descriptor.current_supply, alice.get_public_address(), null_pkey);
|
||||
CHECK_AND_ASSERT_GREATER(m_ado_emit.opt_descriptor->current_supply, ado_register.opt_descriptor->current_supply);
|
||||
destinations.emplace_back(m_ado_emit.opt_descriptor->current_supply - ado_register.opt_descriptor->current_supply, alice.get_public_address(), null_pkey);
|
||||
|
||||
fill_ado_version_based_onhardfork(m_ado_emit, hf_n);
|
||||
if (m_ado_emit.opt_descriptor.has_value()) fill_adb_version_based_onhardfork(*m_ado_emit.opt_descriptor, hf_n);
|
||||
|
||||
ftp.sources = sources;
|
||||
ftp.prepared_destinations = destinations;
|
||||
ftp.tx_version = get_tx_version(get_block_height(top), m_hardforks);
|
||||
ftp.extra = {m_ado_emit};
|
||||
ftp.shuffle = true;
|
||||
CHECK_AND_ASSERT_GREATER(m_ado_emit.descriptor.current_supply, m_ado_emit.descriptor.total_max_supply);
|
||||
CHECK_AND_ASSERT_GREATER(m_ado_emit.opt_descriptor->current_supply, m_ado_emit.opt_descriptor->total_max_supply);
|
||||
success = construct_tx(alice.get_keys(), ftp, ftx);
|
||||
CHECK_AND_ASSERT_EQ(success, true);
|
||||
tx_4 = ftx.tx;
|
||||
|
|
@ -2153,7 +2235,7 @@ bool asset_current_and_total_supplies_comparative_constraints::assert_asset_alph
|
|||
{
|
||||
const std::shared_ptr alice_wallet{init_playtime_test_wallet_t<tools::wallet2>(events, c, ALICE_ACC_IDX)};
|
||||
crypto::public_key alpha_asset_id{};
|
||||
const std::string ticker{m_ados_register.at(asset_position::alpha).descriptor.ticker};
|
||||
const std::string ticker{m_ados_register.at(asset_position::alpha).opt_descriptor->ticker};
|
||||
|
||||
alice_wallet->refresh();
|
||||
|
||||
|
|
@ -2176,7 +2258,7 @@ bool asset_current_and_total_supplies_comparative_constraints::assert_asset_beta
|
|||
{
|
||||
const std::shared_ptr alice_wallet{init_playtime_test_wallet_t<tools::wallet2>(events, c, ALICE_ACC_IDX)};
|
||||
crypto::public_key key_beta_asset_id{};
|
||||
const std::string ticker{m_ados_register.at(asset_position::beta).descriptor.ticker};
|
||||
const std::string ticker{m_ados_register.at(asset_position::beta).opt_descriptor->ticker};
|
||||
|
||||
alice_wallet->refresh();
|
||||
|
||||
|
|
@ -2220,11 +2302,11 @@ bool asset_current_and_total_supplies_comparative_constraints::emit_asset_beta_w
|
|||
{
|
||||
const auto& ado_register{m_ados_register.at(asset_position::beta)};
|
||||
|
||||
CHECK_AND_ASSERT_GREATER(m_ado_emit.descriptor.current_supply, ado_register.descriptor.current_supply);
|
||||
destinations.emplace_back(m_ado_emit.descriptor.current_supply - ado_register.descriptor.current_supply, alice_wallet->get_account().get_public_address(), beta_asset_id);
|
||||
CHECK_AND_ASSERT_GREATER(m_ado_emit.opt_descriptor->current_supply, ado_register.opt_descriptor->current_supply);
|
||||
destinations.emplace_back(m_ado_emit.opt_descriptor->current_supply - ado_register.opt_descriptor->current_supply, alice_wallet->get_account().get_public_address(), beta_asset_id);
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_GREATER(m_ado_emit.descriptor.current_supply, m_ado_emit.descriptor.total_max_supply);
|
||||
CHECK_AND_ASSERT_GREATER(m_ado_emit.opt_descriptor->current_supply, m_ado_emit.opt_descriptor->total_max_supply);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -2260,10 +2342,11 @@ bool asset_current_and_total_supplies_comparative_constraints::assert_asset_beta
|
|||
}
|
||||
|
||||
{
|
||||
const uint64_t& current_supply{register_ado.descriptor.current_supply};
|
||||
const uint64_t& current_supply{register_ado.opt_descriptor->current_supply};
|
||||
|
||||
CHECK_AND_ASSERT_MES(alice_wallet->balance(beta_asset_id) == current_supply, false, "Alice has got not exactly " + std::to_string(current_supply) + ' ' + register_ado.descriptor.ticker);
|
||||
CHECK_AND_ASSERT_MES(alice_wallet->balance(beta_asset_id) == current_supply, false, "Alice has got not exactly " + std::to_string(current_supply) + ' ' + register_ado.opt_descriptor->ticker);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool asset_current_and_total_supplies_comparative_constraints::public_burn_asset_beta_with_incorrect_supply(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events) const
|
||||
|
|
@ -2283,7 +2366,7 @@ bool asset_current_and_total_supplies_comparative_constraints::public_burn_asset
|
|||
{
|
||||
transaction tx{};
|
||||
|
||||
alice_wallet->burn_asset(beta_asset_id, m_ado_emit.descriptor.current_supply, tx);
|
||||
alice_wallet->burn_asset(beta_asset_id, m_ado_emit.opt_descriptor->current_supply, tx);
|
||||
}
|
||||
catch (const std::runtime_error&)
|
||||
{
|
||||
|
|
@ -2298,7 +2381,7 @@ bool asset_current_and_total_supplies_comparative_constraints::assert_asset_gamm
|
|||
{
|
||||
const std::shared_ptr alice_wallet{init_playtime_test_wallet_t<tools::wallet2>(events, c, ALICE_ACC_IDX)};
|
||||
crypto::public_key key_gamma_asset_id{};
|
||||
const std::string ticker{m_ados_register.at(asset_position::gamma).descriptor.ticker};
|
||||
const std::string ticker{m_ados_register.at(asset_position::gamma).opt_descriptor->ticker};
|
||||
|
||||
alice_wallet->refresh();
|
||||
|
||||
|
|
@ -2314,7 +2397,189 @@ bool asset_current_and_total_supplies_comparative_constraints::assert_asset_gamm
|
|||
CHECK_AND_ASSERT_MES(c.get_blockchain_storage().get_asset_info(key_gamma_asset_id, gamma_adb), false, "the asset " + ticker + " must be registered");
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_EQ(alice_wallet->balance(key_gamma_asset_id), m_ados_register.at(asset_position::gamma).descriptor.current_supply);
|
||||
CHECK_AND_ASSERT_EQ(alice_wallet->balance(key_gamma_asset_id), m_ados_register.at(asset_position::gamma).opt_descriptor->current_supply);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
several_asset_emit_burn_txs_in_pool::several_asset_emit_burn_txs_in_pool()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(several_asset_emit_burn_txs_in_pool, c1);
|
||||
}
|
||||
|
||||
bool several_asset_emit_burn_txs_in_pool::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
//
|
||||
// Test idea: make sure two asset emit or two asset burn tx can be added to the pool for the same asset.
|
||||
//
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
|
||||
// rebuild genesis miner tx
|
||||
std::vector<tx_destination_entry> destinations;
|
||||
destinations.emplace_back(MK_TEST_COINS(1), alice_acc.get_public_address());
|
||||
destinations.emplace_back(MK_TEST_COINS(1), alice_acc.get_public_address());
|
||||
CHECK_AND_ASSERT_MES(replace_coinbase_in_genesis_block(destinations, generator, events, blk_0), false, ""); // leftover amount will be also send to miner
|
||||
|
||||
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool several_asset_emit_burn_txs_in_pool::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX);
|
||||
miner_wlt->refresh();
|
||||
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX);
|
||||
alice_wlt->refresh();
|
||||
|
||||
// asset description
|
||||
asset_descriptor_base adb{};
|
||||
adb.decimal_point = 3;
|
||||
adb.total_max_supply = 10'000;
|
||||
adb.full_name = "Lets gooo!";
|
||||
adb.ticker = "BRNDN";
|
||||
|
||||
uint64_t initial_register_amount = 5'000;
|
||||
|
||||
// 1. Miner registers an asset and sends some initial amount to Alice
|
||||
std::vector<tx_destination_entry> destinations;
|
||||
destinations.emplace_back(initial_register_amount, m_accounts[ALICE_ACC_IDX].get_public_address(), null_pkey);
|
||||
finalized_tx ft{};
|
||||
crypto::public_key asset_id{};
|
||||
miner_wlt->deploy_new_asset(adb, destinations, ft, asset_id);
|
||||
LOG_PRINT_GREEN_L0("Asset " << asset_id << " was successfully deployed with tx " << ft.tx_id);
|
||||
|
||||
// make sure tx was added to the pool, then mine a block to confirm it
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
CHECK_AND_ASSERT_MES(mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c), false, "");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
size_t blocks_fetched = 0;
|
||||
miner_wlt->refresh(blocks_fetched);
|
||||
CHECK_AND_ASSERT_EQ(blocks_fetched, 1);
|
||||
|
||||
// Alice checks her asset balance
|
||||
alice_wlt->refresh(blocks_fetched);
|
||||
CHECK_AND_ASSERT_EQ(blocks_fetched, 1);
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", initial_register_amount, asset_id, adb.decimal_point), false, "");
|
||||
|
||||
|
||||
//
|
||||
// 2. Miner emits additional amount of the asset in two transactions (all goes to Alice)
|
||||
//
|
||||
|
||||
// 2.1 the first emit
|
||||
uint64_t additional_emit_amount = 2'500;
|
||||
uint64_t total_asset_amount = initial_register_amount + additional_emit_amount;
|
||||
|
||||
destinations.clear();
|
||||
destinations.emplace_back(additional_emit_amount, m_accounts[ALICE_ACC_IDX].get_public_address(), null_pkey);
|
||||
ft = finalized_tx{};
|
||||
miner_wlt->emit_asset(asset_id, destinations, ft);
|
||||
|
||||
// make sure tx was added to the pool
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
// Alice checks her asset balance (including unconfirmed txs)
|
||||
alice_wlt->refresh(blocks_fetched);
|
||||
CHECK_AND_ASSERT_EQ(blocks_fetched, 0);
|
||||
bool stub{};
|
||||
alice_wlt->scan_tx_pool(stub);
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", total_asset_amount, asset_id, adb.decimal_point), false, "");
|
||||
|
||||
// 2.2 the second emit
|
||||
additional_emit_amount = 2'500;
|
||||
total_asset_amount += additional_emit_amount;
|
||||
|
||||
destinations.clear();
|
||||
destinations.emplace_back(additional_emit_amount, m_accounts[ALICE_ACC_IDX].get_public_address(), null_pkey);
|
||||
ft = finalized_tx{};
|
||||
miner_wlt->emit_asset(asset_id, destinations, ft);
|
||||
|
||||
// make sure the second tx was added to the pool
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 2, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
// Alice checks her asset balance (including unconfirmed txs)
|
||||
alice_wlt->refresh(blocks_fetched);
|
||||
CHECK_AND_ASSERT_EQ(blocks_fetched, 0);
|
||||
alice_wlt->scan_tx_pool(stub);
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", total_asset_amount, asset_id, adb.decimal_point), false, "");
|
||||
|
||||
// 2.3
|
||||
// mine a block to confirm both txs to make sure everything is alright
|
||||
CHECK_AND_ASSERT_MES(mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c), false, "");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
alice_wlt->refresh(blocks_fetched);
|
||||
CHECK_AND_ASSERT_EQ(blocks_fetched, 1);
|
||||
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", total_asset_amount, asset_id, adb.decimal_point), false, "");
|
||||
|
||||
|
||||
// make sure these txs are fully confirmed
|
||||
CHECK_AND_ASSERT_MES(mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW), false, "");
|
||||
|
||||
|
||||
//
|
||||
// 3. Alice burns amount of the asset in two transactions
|
||||
//
|
||||
alice_wlt->refresh();
|
||||
|
||||
// 3.1, the first burn
|
||||
uint64_t burn_amount = 2'500;
|
||||
total_asset_amount -= burn_amount;
|
||||
|
||||
ft = finalized_tx{};
|
||||
alice_wlt->burn_asset(asset_id, burn_amount, ft);
|
||||
|
||||
// make sure tx was added to the pool
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
alice_wlt->refresh(blocks_fetched);
|
||||
CHECK_AND_ASSERT_EQ(blocks_fetched, 0);
|
||||
alice_wlt->scan_tx_pool(stub);
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", total_asset_amount, asset_id, adb.decimal_point), false, "");
|
||||
|
||||
// 3.2, the second burn
|
||||
burn_amount = 2'500;
|
||||
total_asset_amount -= burn_amount;
|
||||
|
||||
ft = finalized_tx{};
|
||||
alice_wlt->burn_asset(asset_id, burn_amount, ft);
|
||||
|
||||
// make sure both txs are now in the pool
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 2, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
alice_wlt->refresh(blocks_fetched);
|
||||
CHECK_AND_ASSERT_EQ(blocks_fetched, 0);
|
||||
alice_wlt->scan_tx_pool(stub);
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", total_asset_amount, asset_id, adb.decimal_point), false, "");
|
||||
|
||||
// 3.3
|
||||
// mine a block to confirm both txs to make sure everything is alright
|
||||
CHECK_AND_ASSERT_MES(mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c), false, "");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
alice_wlt->refresh(blocks_fetched);
|
||||
CHECK_AND_ASSERT_EQ(blocks_fetched, 1);
|
||||
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", total_asset_amount, asset_id, adb.decimal_point), false, "");
|
||||
|
||||
// make sure these txs are fully confirmed
|
||||
CHECK_AND_ASSERT_MES(mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW), false, "");
|
||||
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", total_asset_amount, asset_id, adb.decimal_point), false, "");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,3 +114,10 @@ private:
|
|||
mutable std::array<currency::asset_descriptor_operation, 3> m_ados_register{};
|
||||
mutable currency::asset_descriptor_operation m_ado_emit{};
|
||||
};
|
||||
|
||||
struct several_asset_emit_burn_txs_in_pool : public wallet_test
|
||||
{
|
||||
several_asset_emit_burn_txs_in_pool();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2571,7 +2571,7 @@ bool multisig_unconfirmed_transfer_and_multiple_scan_pool_calls::c1(currency::co
|
|||
LOG_PRINT_YELLOW("%%%%% tx " << get_transaction_hash(tx) << " is spending multisig output " << multisig_id, LOG_LEVEL_0);
|
||||
|
||||
bool stub;
|
||||
std::deque<tools::transfer_details> transfers;
|
||||
tools::transfer_container transfers;
|
||||
std::vector<tools::wallet_public::wallet_transfer_info> unconfirmed_transfers;
|
||||
|
||||
alice_wlt->scan_tx_pool(stub);
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ void pos_block_builder::step5_sign(const currency::tx_source_entry& se, const cu
|
|||
|
||||
// range proofs
|
||||
currency::zc_outs_range_proof range_proofs{};
|
||||
r = generate_zc_outs_range_proof(miner_tx_id, 0, m_miner_tx_tgc, m_block.miner_tx.vout, range_proofs);
|
||||
r = generate_zc_outs_range_proof(miner_tx_id, m_miner_tx_tgc, m_block.miner_tx.vout, range_proofs);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "Failed to generate zc_outs_range_proof()");
|
||||
m_block.miner_tx.proofs.emplace_back(std::move(range_proofs));
|
||||
|
||||
|
|
|
|||
|
|
@ -1711,7 +1711,6 @@ bool tx_pool_semantic_validation::generate(std::vector<test_event_entry>& events
|
|||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner, test_core_time::get_time());
|
||||
DO_CALLBACK(events, "configure_core");
|
||||
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(transaction{}, CURRENCY_MAX_TRANSACTION_BLOB_SIZE), false);
|
||||
|
||||
// No inputs.
|
||||
|
|
@ -1728,7 +1727,7 @@ bool tx_pool_semantic_validation::generate(std::vector<test_event_entry>& events
|
|||
{
|
||||
transaction tx{};
|
||||
|
||||
tx.vin.emplace_back();
|
||||
tx.vin.emplace_back(txin_gen{});
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), false);
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx);
|
||||
|
|
@ -1750,7 +1749,6 @@ bool tx_pool_semantic_validation::generate(std::vector<test_event_entry>& events
|
|||
point_t point_public_key{};
|
||||
txout_to_key target{};
|
||||
std::array<txin_to_key, 2> inputs{};
|
||||
tx_out_bare output{};
|
||||
transaction tx{};
|
||||
|
||||
CHECK_AND_ASSERT_EQ(point_public_key.from_string("499790c3302b9f0514e2db09b390679283d43d971383d33dc24c7991ea4cf6d7"), true);
|
||||
|
|
@ -1763,10 +1761,6 @@ bool tx_pool_semantic_validation::generate(std::vector<test_event_entry>& events
|
|||
tx.vin.push_back(input);
|
||||
}
|
||||
|
||||
output.amount = 1;
|
||||
output.target = target;
|
||||
tx.vout.push_back(output);
|
||||
|
||||
CHECK_AND_ASSERT_GREATER(inputs.at(0).amount, inputs.at(0).amount + inputs.at(1).amount);
|
||||
CHECK_AND_ASSERT_GREATER(inputs.at(1).amount, inputs.at(0).amount + inputs.at(1).amount);
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), false);
|
||||
|
|
@ -1803,41 +1797,50 @@ bool tx_pool_semantic_validation::generate(std::vector<test_event_entry>& events
|
|||
|
||||
// Equal key images in inputs.
|
||||
{
|
||||
tx_out_bare output;
|
||||
transaction tx{};
|
||||
std::array<txin_to_key, 2> inputs{};
|
||||
point_t key_image_point{};
|
||||
key_image image{};
|
||||
|
||||
output.amount = 1;
|
||||
tx.vout.push_back(output);
|
||||
CHECK_AND_ASSERT_EQ(key_image_point.from_string("8fc7cbfd1054690767d0c20917a68371b34b190aac5997581641f064b93d1b96"), true);
|
||||
image = key_image_point.to_key_image();
|
||||
|
||||
for (int position{}; position < 2; ++position)
|
||||
{
|
||||
inputs.at(position).k_image = image;
|
||||
tx.vin.push_back(inputs.at(position));
|
||||
txin_zc_input input_zc{};
|
||||
txin_htlc input_htlc{};
|
||||
txin_to_key input_to_key{};
|
||||
point_t point_key_image{};
|
||||
|
||||
CHECK_AND_ASSERT_EQ(point_key_image.from_string("93fa59f43fb9cff98e6867d20cf200c98b29cae406acdbde798ffb3e30d3503a"), true);
|
||||
input_zc.k_image = point_key_image.to_key_image();
|
||||
CHECK_AND_ASSERT_EQ(point_key_image.from_string("ad1226e3fd1be15e26b119fa80380e580a498e5fa3421b63fded89672b526a44"), true);
|
||||
input_htlc.k_image = point_key_image.to_key_image();
|
||||
CHECK_AND_ASSERT_EQ(point_key_image.from_string("8fc7cbfd1054690767d0c20917a68371b34b190aac5997581641f064b93d1b96"), true);
|
||||
input_to_key.k_image = point_key_image.to_key_image();
|
||||
tx.vin.push_back(input_zc);
|
||||
tx.vin.push_back(input_htlc);
|
||||
tx.vin.push_back(input_to_key);
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_EQ(tx.vin.at(0).type(), typeid(txin_to_key));
|
||||
CHECK_AND_ASSERT_EQ(tx.vin.at(0).type(), tx.vin.at(1).type());
|
||||
CHECK_AND_ASSERT_EQ(boost::get<txin_to_key>(tx.vin.at(0)).k_image, boost::get<txin_to_key>(tx.vin.at(1)).k_image);
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), false);
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx);
|
||||
{
|
||||
txin_to_key input{};
|
||||
|
||||
input.amount = 0;
|
||||
tx.vin.push_back(input);
|
||||
}
|
||||
|
||||
for (int8_t step{}; step < 3; ++step)
|
||||
{
|
||||
tx.vin.push_back(tx.vin.front());
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), false);
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx);
|
||||
tx.vin.erase(tx.vin.begin(), tx.vin.begin() + 1);
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), true);
|
||||
}
|
||||
|
||||
// Two entries of the same type in extra.
|
||||
{
|
||||
tx_out_bare output;
|
||||
transaction tx{};
|
||||
std::array<txin_to_key, 2> inputs{};
|
||||
std::array<point_t, 2> key_image_points{};
|
||||
key_image image{};
|
||||
|
||||
output.amount = 1;
|
||||
tx.vout.push_back(output);
|
||||
CHECK_AND_ASSERT_EQ(key_image_points.at(0).from_string("de3c22a62f15e6de8abe6b217085b2aead196daf5ddd67d9c4b366330736fbeb"), true);
|
||||
CHECK_AND_ASSERT_EQ(key_image_points.at(1).from_string("9f3eef913921ca35239e696725595e3686bb0d69e3e805791c5aa93d5754aa5c"), true);
|
||||
|
||||
|
|
@ -1859,8 +1862,8 @@ bool tx_pool_semantic_validation::generate(std::vector<test_event_entry>& events
|
|||
|
||||
// tx.version <= TRANSACTION_VERSION_PRE_HF4. Balance check fail: sum of inputs <= sum of outputs.
|
||||
{
|
||||
tx_out_bare output{};
|
||||
transaction tx{};
|
||||
tx_out_bare output;
|
||||
std::array<point_t, 2> key_image_points{};
|
||||
std::array<txin_to_key, 2> inputs{};
|
||||
|
||||
|
|
@ -1879,7 +1882,10 @@ bool tx_pool_semantic_validation::generate(std::vector<test_event_entry>& events
|
|||
tx.vin.push_back(input);
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_GREATER(output.amount, std::accumulate(inputs.begin(), inputs.end(), std::uint64_t{}, [](uint64_t sum, const txin_to_key& input) { return sum + input.amount; }));
|
||||
const uint64_t sum_inputs{std::accumulate(inputs.begin(), inputs.end(), std::uint64_t{}, [](uint64_t sum, const txin_to_key& input) { return sum + input.amount; })};
|
||||
|
||||
CHECK_AND_ASSERT_LESS(sum_inputs, output.amount);
|
||||
CHECK_AND_ASSERT_EQ(output.amount - sum_inputs, 1);
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), false);
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx);
|
||||
|
|
@ -1911,5 +1917,207 @@ bool tx_pool_semantic_validation::generate(std::vector<test_event_entry>& events
|
|||
ADD_CUSTOM_EVENT(events, tx);
|
||||
}
|
||||
|
||||
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
// Construct a valid transaction and then modify it so that the transaction is no longer semantically correct.
|
||||
|
||||
// No inputs.
|
||||
{
|
||||
MAKE_TX_FEE(events, tx, miner, miner, MK_TEST_COINS(2), TESTS_DEFAULT_FEE, blk_0r);
|
||||
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), true);
|
||||
tx.vin = {};
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), false);
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx);
|
||||
}
|
||||
|
||||
// Unsupported input type.
|
||||
{
|
||||
MAKE_TX_FEE(events, tx, miner, miner, MK_TEST_COINS(2), TESTS_DEFAULT_FEE, blk_0r);
|
||||
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), true);
|
||||
tx.vin.emplace_back(txin_gen{});
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), false);
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx);
|
||||
}
|
||||
|
||||
// Unsupported output type.
|
||||
{
|
||||
MAKE_TX_FEE(events, tx, miner, miner, MK_TEST_COINS(2), TESTS_DEFAULT_FEE, blk_0r);
|
||||
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), true);
|
||||
tx.vout.emplace_back();
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), false);
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx);
|
||||
}
|
||||
|
||||
// Inputs amount overflow.
|
||||
{
|
||||
point_t point_public_key{};
|
||||
txout_to_key target{};
|
||||
std::array<txin_to_key, 2> inputs{};
|
||||
MAKE_TX_FEE(events, tx, miner, miner, MK_TEST_COINS(2), TESTS_DEFAULT_FEE, blk_0r);
|
||||
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), true);
|
||||
CHECK_AND_ASSERT_EQ(point_public_key.from_string("499790c3302b9f0514e2db09b390679283d43d971383d33dc24c7991ea4cf6d7"), true);
|
||||
target.key = point_public_key.to_public_key();
|
||||
inputs.at(0).amount = 1;
|
||||
inputs.at(1).amount = UINT64_MAX;
|
||||
|
||||
for (const auto& input : inputs)
|
||||
{
|
||||
tx.vin.push_back(input);
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_GREATER(inputs.at(0).amount, inputs.at(0).amount + inputs.at(1).amount);
|
||||
CHECK_AND_ASSERT_GREATER(inputs.at(1).amount, inputs.at(0).amount + inputs.at(1).amount);
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), false);
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx);
|
||||
}
|
||||
|
||||
// Outputs amount overflow.
|
||||
{
|
||||
point_t point_public_key{};
|
||||
txout_to_key target{};
|
||||
std::array<tx_out_bare, 2> outputs{};
|
||||
MAKE_TX_FEE(events, tx, miner, miner, MK_TEST_COINS(2), TESTS_DEFAULT_FEE, blk_0r);
|
||||
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), true);
|
||||
CHECK_AND_ASSERT_EQ(point_public_key.from_string("78ef3d9af7b5e3d09556d57820cf68c2b3553a9d8205c01fe40fc70aae86bb4f"), true);
|
||||
target.key = point_public_key.to_public_key();
|
||||
outputs.at(0).amount = 1;
|
||||
outputs.at(1).amount = UINT64_MAX;
|
||||
|
||||
for (auto& output : outputs)
|
||||
{
|
||||
output.target = target;
|
||||
tx.vout.push_back(output);
|
||||
}
|
||||
|
||||
tx.vin.push_back(txin_to_key{});
|
||||
|
||||
CHECK_AND_ASSERT_GREATER(outputs.at(0).amount, outputs.at(0).amount + outputs.at(1).amount);
|
||||
CHECK_AND_ASSERT_GREATER(outputs.at(1).amount, outputs.at(0).amount + outputs.at(1).amount);
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), false);
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx);
|
||||
}
|
||||
|
||||
// Equal key images in inputs.
|
||||
{
|
||||
MAKE_TX_FEE(events, tx, miner, miner, MK_TEST_COINS(2), TESTS_DEFAULT_FEE, blk_0r);
|
||||
|
||||
{
|
||||
txin_zc_input input_zc{};
|
||||
txin_htlc input_htlc{};
|
||||
txin_to_key input_to_key{};
|
||||
point_t point_key_image{};
|
||||
|
||||
CHECK_AND_ASSERT_EQ(point_key_image.from_string("93fa59f43fb9cff98e6867d20cf200c98b29cae406acdbde798ffb3e30d3503a"), true);
|
||||
input_zc.k_image = point_key_image.to_key_image();
|
||||
CHECK_AND_ASSERT_EQ(point_key_image.from_string("ad1226e3fd1be15e26b119fa80380e580a498e5fa3421b63fded89672b526a44"), true);
|
||||
input_htlc.k_image = point_key_image.to_key_image();
|
||||
CHECK_AND_ASSERT_EQ(point_key_image.from_string("8fc7cbfd1054690767d0c20917a68371b34b190aac5997581641f064b93d1b96"), true);
|
||||
input_to_key.k_image = point_key_image.to_key_image();
|
||||
tx.vin.push_back(input_zc);
|
||||
tx.vin.push_back(input_htlc);
|
||||
tx.vin.push_back(input_to_key);
|
||||
}
|
||||
|
||||
for (int8_t step{}; step < 3; ++step)
|
||||
{
|
||||
tx.vin.push_back(tx.vin.front());
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), false);
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx);
|
||||
tx.vin.erase(tx.vin.begin(), tx.vin.begin() + 1);
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), true);
|
||||
}
|
||||
|
||||
// Two entries of the same type in extra.
|
||||
{
|
||||
MAKE_TX_FEE(events, tx, miner, miner, MK_TEST_COINS(2), TESTS_DEFAULT_FEE, blk_0r);
|
||||
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), true);
|
||||
tx.extra.push_back(null_pkey);
|
||||
tx.extra.push_back(null_pkey);
|
||||
|
||||
CHECK_AND_ASSERT_GREATER(tx.extra.size(), 2);
|
||||
CHECK_AND_ASSERT_EQ(typeid(tx.extra.back()), typeid(tx.extra.at(tx.extra.size() - 2)));
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), false);
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx);
|
||||
}
|
||||
|
||||
// tx.version <= TRANSACTION_VERSION_PRE_HF4. Balance check fail: sum of inputs <= sum of outputs.
|
||||
{
|
||||
tx_out_bare output{};
|
||||
std::array<point_t, 2> key_image_points{};
|
||||
std::array<txin_to_key, 2> inputs{};
|
||||
MAKE_TX_FEE(events, tx, miner, miner, MK_TEST_COINS(1), TESTS_DEFAULT_FEE, blk_0r);
|
||||
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), true);
|
||||
output.amount = 10'000'000'003;
|
||||
tx.vout.push_back(output);
|
||||
tx.version = 0;
|
||||
CHECK_AND_ASSERT_EQ(key_image_points.at(0).from_string("8fc7cbfd1054690767d0c20917a68371b34b190aac5997581641f064b93d1b96"), true);
|
||||
CHECK_AND_ASSERT_EQ(key_image_points.at(1).from_string("dc48b741dacda5ac026ad0a7d193b816049eb08724907a1ff6f95839cfb0efa5"), true);
|
||||
|
||||
for (int position{}; position < 2; ++position)
|
||||
{
|
||||
auto& input{inputs.at(position)};
|
||||
|
||||
input.amount = 1;
|
||||
input.k_image = key_image_points.at(position).to_key_image();
|
||||
tx.vin.push_back(input);
|
||||
}
|
||||
|
||||
const auto inputs_sum{[](const uint64_t sum, const txin_v& input) -> uint64_t
|
||||
{
|
||||
if (input.type() == typeid(txin_to_key))
|
||||
{
|
||||
return sum + boost::get<txin_to_key>(input).amount;
|
||||
}
|
||||
|
||||
if (input.type() == typeid(txin_multisig))
|
||||
{
|
||||
return sum + boost::get<txin_multisig>(input).amount;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
|
||||
const auto outputs_sum{[](const uint64_t sum, const tx_out_v& output) -> uint64_t
|
||||
{
|
||||
if (output.type() == typeid(tx_out_bare))
|
||||
{
|
||||
return sum + boost::get<tx_out_bare>(output).amount;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
|
||||
const uint64_t inputs_amount{std::accumulate(tx.vin.begin(), tx.vin.end(), std::uint64_t{}, inputs_sum)};
|
||||
const uint64_t outputs_amount{std::accumulate(tx.vout.begin(), tx.vout.end(), std::uint64_t{}, outputs_sum)};
|
||||
|
||||
CHECK_AND_ASSERT_LESS(inputs_amount, outputs_amount);
|
||||
CHECK_AND_ASSERT_EQ(outputs_amount - inputs_amount, 1);
|
||||
CHECK_AND_ASSERT(tx.version <= TRANSACTION_VERSION_PRE_HF4, false);
|
||||
CHECK_AND_ASSERT_EQ(get_block_height(blk_0r), 10);
|
||||
CHECK_AND_ASSERT_EQ(m_hardforks.is_hardfork_active_for_height(ZANO_HARDFORK_03, 10), true);
|
||||
CHECK_AND_ASSERT_EQ(m_hardforks.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, 10), false);
|
||||
CHECK_AND_ASSERT_EQ(validate_tx_semantic(tx, CURRENCY_MAX_TRANSACTION_BLOB_SIZE - 1), false);
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ struct tx_version_against_hardfork : public test_chain_unit_enchanced
|
|||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
};
|
||||
|
||||
struct tx_pool_semantic_validation : public test_chain_unit_enchanced
|
||||
struct tx_pool_semantic_validation : public test_chain_unit_enchanced
|
||||
{
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ bool wallet_test_core_proxy::call_COMMAND_RPC_GET_BLOCKS_FAST(const currency::CO
|
|||
|
||||
rsp.current_height = m_blocks.size();
|
||||
rsp.status = API_RETURN_CODE_OK;
|
||||
if (!m_first_call)
|
||||
if (!m_first_call && rsp.start_height != 0 /*second condition needed for re-sync in concise_mode*/)
|
||||
{
|
||||
m_first_call = true;
|
||||
return true; // respond with empty blocks on second call to gracefully stop wallet refreshing
|
||||
|
|
|
|||
|
|
@ -1490,6 +1490,9 @@ bool gen_wallet_decrypted_attachments::generate(std::vector<test_event_entry>& e
|
|||
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
CREATE_TEST_WALLET(alice_wlt, alice_acc, blk_0);
|
||||
//disable concise because this test count on on_transfer callbacks and resync cause firing on_transfer() for previous transactions
|
||||
alice_wlt->set_concise_mode(false);
|
||||
|
||||
REFRESH_TEST_WALLET_AT_GEN_TIME(events, alice_wlt, blk_0r, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
// these attachments will be used across all the transactions in this test
|
||||
|
|
@ -3819,6 +3822,7 @@ bool wallet_and_sweep_below::c1(currency::core& c, size_t ev_index, const std::v
|
|||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
block_template_blacklist_test::block_template_blacklist_test()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(block_template_blacklist_test, c1);
|
||||
|
|
@ -3908,3 +3912,64 @@ bool block_template_blacklist_test::c1(currency::core& c, size_t ev_index, const
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
wallet_reorganize_and_trim_test::wallet_reorganize_and_trim_test()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(wallet_reorganize_and_trim_test, c1);
|
||||
}
|
||||
|
||||
bool wallet_reorganize_and_trim_test::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(1);
|
||||
account_base preminer_acc;
|
||||
preminer_acc.generate();
|
||||
preminer_acc.set_createtime(ts);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, preminer_acc, ts);
|
||||
DO_CALLBACK(events, "configure_core");
|
||||
|
||||
MAKE_NEXT_BLOCK(events, blk_1, blk_0, preminer_acc);
|
||||
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, 2 * CURRENCY_MINED_MONEY_UNLOCK_WINDOW - 1);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool wallet_reorganize_and_trim_test::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX);
|
||||
//mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, 2);
|
||||
#define WALLET_REORGANIZE_AND_TRIM_TEST_REORG_SIZE 10
|
||||
miner_wlt->set_concise_mode(true);
|
||||
miner_wlt->set_concise_mode_reorg_max_reorg_blocks(6);
|
||||
|
||||
account_base acc;
|
||||
acc.generate();
|
||||
std::shared_ptr<tools::wallet2> alice = init_playtime_test_wallet(events, c, acc);
|
||||
miner_wlt->refresh();
|
||||
miner_wlt->transfer(COIN, alice->get_account().get_public_address());
|
||||
mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, 2);
|
||||
|
||||
mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, WALLET_REORGANIZE_AND_TRIM_TEST_REORG_SIZE);
|
||||
uint64_t h1 = c.get_blockchain_storage().get_top_block_height();
|
||||
miner_wlt->refresh();
|
||||
uint64_t unlocked = 0;
|
||||
uint64_t total = miner_wlt->balance(unlocked);
|
||||
|
||||
c.get_blockchain_storage().truncate_blockchain(c.get_blockchain_storage().get_top_block_height() - (WALLET_REORGANIZE_AND_TRIM_TEST_REORG_SIZE-1));
|
||||
mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, 10);
|
||||
uint64_t h2 = c.get_blockchain_storage().get_top_block_height();
|
||||
miner_wlt->refresh();
|
||||
uint64_t unlocked2 = 0;
|
||||
uint64_t total2 = miner_wlt->balance(unlocked2);
|
||||
if (unlocked2 != unlocked || total2 != total)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(false, false, "wallet concise mode check failed");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -301,4 +301,11 @@ struct block_template_blacklist_test : public wallet_test
|
|||
block_template_blacklist_test();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
};
|
||||
|
||||
struct wallet_reorganize_and_trim_test : public wallet_test
|
||||
{
|
||||
wallet_reorganize_and_trim_test();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
};
|
||||
|
|
@ -60,6 +60,8 @@ struct wallet_test : virtual public test_chain_unit_enchanced
|
|||
w->set_genesis(genesis_hash);
|
||||
w->set_core_proxy(m_core_proxy);
|
||||
w->set_disable_tor_relay(true);
|
||||
w->set_concise_mode(true);
|
||||
w->set_concise_mode_reorg_max_reorg_blocks(TESTS_CONCISE_MODE_REORG_MAX_REORG_BLOCK);
|
||||
return w;
|
||||
|
||||
#undef LOCAL_HOST_CSTR
|
||||
|
|
|
|||
|
|
@ -450,7 +450,7 @@ namespace boost
|
|||
bool core_concurrency_test(boost::program_options::variables_map& vm, size_t wthreads, size_t rthreads, size_t blocks_count)
|
||||
{
|
||||
log_space::get_set_log_detalisation_level(true, LOG_LEVEL_0);
|
||||
//epee::debug::get_set_enable_assert(true, false);
|
||||
epee::debug::get_set_enable_assert(true, false);
|
||||
log_space::get_set_need_thread_id(true, true);
|
||||
|
||||
cct_accounts_t accounts(s_wallets_total_count);
|
||||
|
|
|
|||
|
|
@ -1966,9 +1966,9 @@ TEST(crypto, generators_precomp)
|
|||
|
||||
#undef CHECK_PRECOMP
|
||||
}
|
||||
|
||||
#include "bitcoin-secp256k1/include/secp256k1.h"
|
||||
TEST(crypto, secp256k1_ecdsa_native)
|
||||
#ifndef USE_OPEN_SSL_FOR_ECDSA
|
||||
#include "bitcoin-secp256k1/include/secp256k1.h"
|
||||
TEST(crypto, secp256k1_ecdsa_native)
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
|
|
@ -2026,7 +2026,7 @@ TEST(crypto, secp256k1_ecdsa_native)
|
|||
secp256k1_context_destroy(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST(crypto, eth_signature_basics)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1340,7 +1340,6 @@ TEST(perf, point_eq_vs_iszero)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
TEST(perf, buff_to_hex)
|
||||
{
|
||||
std::vector<std::string> in_buffs;
|
||||
|
|
|
|||
|
|
@ -197,9 +197,9 @@ uint64_t got_money_in_first_transfers(const tools::transfer_container& incoming_
|
|||
{
|
||||
uint64_t summ = 0;
|
||||
size_t count = 0;
|
||||
BOOST_FOREACH(const tools::transfer_details& td, incoming_transfers)
|
||||
for(auto& tr : incoming_transfers)
|
||||
{
|
||||
summ += boost::get<tx_out_bare>(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]).amount;
|
||||
summ += boost::get<tx_out_bare>(tr.second.m_ptx_wallet_info->m_tx.vout[tr.second.m_internal_output_index]).amount;
|
||||
if(++count >= n_transfers)
|
||||
return summ;
|
||||
}
|
||||
|
|
@ -245,9 +245,9 @@ std::string get_incoming_transfers_str(tools::wallet2& w)
|
|||
|
||||
uint64_t spent_count = 0;
|
||||
uint64_t unspent_count = 0;
|
||||
for (const auto& td : transfers)
|
||||
for (const auto& tr : transfers)
|
||||
{
|
||||
if (td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_SPENT)
|
||||
if (tr.second.m_flags&WALLET_TRANSFER_DETAIL_FLAG_SPENT)
|
||||
{
|
||||
++spent_count;
|
||||
}
|
||||
|
|
@ -469,8 +469,9 @@ bool transactions_flow_test(
|
|||
//lets go!
|
||||
size_t count = 0;
|
||||
prepared_transfers = 0;
|
||||
BOOST_FOREACH(tools::transfer_details& td, incoming_transfers)
|
||||
for(const auto& tr : incoming_transfers)
|
||||
{
|
||||
const tools::transfer_details& td = tr.second;
|
||||
if (td.is_spent())
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,9 +24,10 @@
|
|||
#include "free_space_check.h"
|
||||
#include "htlc_hash_tests.h"
|
||||
#include "threads_pool_tests.h"
|
||||
#include "wallet/plain_wallet_api.h"
|
||||
#include "wallet/plain_wallet_api.h"
|
||||
#include "wallet/view_iface.h"
|
||||
|
||||
#include "wallet/plain_wallet_api_defs.h"
|
||||
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4244)
|
||||
#include "jwt-cpp/jwt.h"
|
||||
|
|
@ -34,9 +35,15 @@ POP_VS_WARNINGS
|
|||
|
||||
void test_plain_wallet()
|
||||
{
|
||||
std::string res = plain_wallet::init("195.201.107.230", "33340", "C:\\Users\\roky\\home\\", 0);
|
||||
//std::string res = plain_wallet::init("195.201.107.230", "33340", "C:\\Users\\roky\\home\\", 0);
|
||||
std::string res = plain_wallet::init("", "", "C:\\Users\\roky\\home\\", 0);
|
||||
//std::string res = plain_wallet::init("127.0.0.1", "12111", "C:\\Users\\roky\\home22\\", 0);
|
||||
|
||||
plain_wallet::configure_object conf = AUTO_VAL_INIT(conf);
|
||||
//plain_wallet::configure_response conf_resp = AUTO_VAL_INIT(conf_resp);
|
||||
conf.postponed_run_wallet = true;
|
||||
std::string r = plain_wallet::sync_call("configure", 0, epee::serialization::store_t_to_json(conf));
|
||||
|
||||
|
||||
std::string res___ = plain_wallet::get_wallet_files();
|
||||
|
||||
|
|
@ -46,6 +53,10 @@ void test_plain_wallet()
|
|||
//res = plain_wallet::restore("",
|
||||
// "test_restored_2.zan", "111", "");
|
||||
|
||||
epee::misc_utils::sleep_no_w(2000);
|
||||
|
||||
res = plain_wallet::sync_call("reset_connection_url", 0, "195.201.107.230:33336");
|
||||
r = plain_wallet::sync_call("run_wallet", instance_id, "");
|
||||
|
||||
while(true)
|
||||
{
|
||||
|
|
@ -53,6 +64,7 @@ void test_plain_wallet()
|
|||
res = plain_wallet::sync_call("get_wallet_status", instance_id, "");
|
||||
view::wallet_sync_status_info wsi = AUTO_VAL_INIT(wsi);
|
||||
epee::serialization::load_t_from_json(wsi, res);
|
||||
LOG_PRINT_L0("Progress: " << wsi.progress);
|
||||
if (wsi.wallet_state == 2)
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -5,21 +5,180 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "common/util.h"
|
||||
|
||||
bool check_parse_client_version(const std::string& str, int expected_major, int expected_minor, int expected_revision, int expected_build_number, const std::string& expected_commit_id, bool expected_dirty)
|
||||
enum class reponse_check_parse_client_version : uint8_t
|
||||
{
|
||||
int major = -1, minor = -1, revision = -1, build_number = -1;
|
||||
std::string commit_id;
|
||||
bool dirty = false;
|
||||
parsed,
|
||||
not_parsed,
|
||||
parsed_unexpect
|
||||
};
|
||||
|
||||
static reponse_check_parse_client_version check_parse_client_version(const std::string& str, const std::optional<int>& expected_major, const std::optional<int>& expected_minor,
|
||||
const std::optional<int>& expected_revision, const std::optional<int>& expected_build_number,
|
||||
const std::optional<std::string>& expected_commit_id, const std::optional<bool>& expected_dirty)
|
||||
{
|
||||
enum class version_integer_component : uint8_t { major, minor, revision, build_number };
|
||||
std::array<int32_t, 4> values_on_not_written{INT32_MIN, INT32_MIN, INT32_MIN, INT32_MIN};
|
||||
int32_t major{}, minor{}, revision{}, build_number{};
|
||||
std::string commit_id{};
|
||||
bool dirty{};
|
||||
|
||||
if (expected_major.has_value() && expected_major.value() == INT32_MIN)
|
||||
{
|
||||
values_on_not_written.at(static_cast<uint8_t>(version_integer_component::major)) = INT32_MAX;
|
||||
}
|
||||
|
||||
if (expected_minor.has_value() && expected_minor.value() == INT32_MIN)
|
||||
{
|
||||
values_on_not_written.at(static_cast<uint8_t>(version_integer_component::minor)) = INT32_MAX;
|
||||
}
|
||||
|
||||
if (expected_revision.has_value() && expected_revision.value() == INT32_MIN)
|
||||
{
|
||||
values_on_not_written.at(static_cast<uint8_t>(version_integer_component::revision)) = INT32_MAX;
|
||||
}
|
||||
|
||||
if (expected_build_number.has_value() && expected_build_number.value() == INT32_MIN)
|
||||
{
|
||||
values_on_not_written.at(static_cast<uint8_t>(version_integer_component::build_number)) = INT32_MAX;
|
||||
}
|
||||
|
||||
major = values_on_not_written.at(static_cast<uint8_t>(version_integer_component::major));
|
||||
minor = values_on_not_written.at(static_cast<uint8_t>(version_integer_component::minor));
|
||||
revision = values_on_not_written.at(static_cast<uint8_t>(version_integer_component::revision));
|
||||
build_number = values_on_not_written.at(static_cast<uint8_t>(version_integer_component::build_number));
|
||||
|
||||
if (expected_commit_id.has_value() && !expected_commit_id.value().empty())
|
||||
{
|
||||
const auto length{expected_commit_id.value().length()};
|
||||
|
||||
assert(length + 1 > length);
|
||||
commit_id = std::string(length + 1, '\0');
|
||||
}
|
||||
|
||||
if (!tools::parse_client_version(str, major, minor, revision, build_number, commit_id, dirty))
|
||||
return false;
|
||||
{
|
||||
return reponse_check_parse_client_version::not_parsed;
|
||||
}
|
||||
|
||||
return major == expected_major && minor == expected_minor && revision == expected_revision && build_number == expected_build_number && commit_id == expected_commit_id && dirty == expected_dirty;
|
||||
if (expected_major.has_value())
|
||||
{
|
||||
if (major == values_on_not_written.at(static_cast<uint8_t>(version_integer_component::major)) || major != expected_major.value())
|
||||
{
|
||||
return reponse_check_parse_client_version::parsed_unexpect;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (major != values_on_not_written.at(static_cast<uint8_t>(version_integer_component::major)))
|
||||
{
|
||||
return reponse_check_parse_client_version::parsed_unexpect;
|
||||
}
|
||||
}
|
||||
|
||||
if (expected_minor.has_value())
|
||||
{
|
||||
if (minor == values_on_not_written.at(static_cast<uint8_t>(version_integer_component::minor)) || minor != expected_minor.value())
|
||||
{
|
||||
return reponse_check_parse_client_version::parsed_unexpect;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (minor != values_on_not_written.at(static_cast<uint8_t>(version_integer_component::minor)))
|
||||
{
|
||||
return reponse_check_parse_client_version::parsed_unexpect;
|
||||
}
|
||||
}
|
||||
|
||||
if (expected_revision.has_value())
|
||||
{
|
||||
if (revision == values_on_not_written.at(static_cast<uint8_t>(version_integer_component::revision)) || revision != expected_revision.value())
|
||||
{
|
||||
return reponse_check_parse_client_version::parsed_unexpect;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (revision != values_on_not_written.at(static_cast<uint8_t>(version_integer_component::revision)))
|
||||
{
|
||||
return reponse_check_parse_client_version::parsed_unexpect;
|
||||
}
|
||||
}
|
||||
|
||||
if (expected_commit_id.has_value())
|
||||
{
|
||||
if (commit_id != expected_commit_id.value())
|
||||
{
|
||||
return reponse_check_parse_client_version::parsed_unexpect;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (!commit_id.empty())
|
||||
{
|
||||
return reponse_check_parse_client_version::parsed_unexpect;
|
||||
}
|
||||
}
|
||||
|
||||
if (expected_dirty.has_value())
|
||||
{
|
||||
if (dirty != expected_dirty.value())
|
||||
{
|
||||
return reponse_check_parse_client_version::parsed_unexpect;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return reponse_check_parse_client_version::parsed_unexpect;
|
||||
}
|
||||
|
||||
return reponse_check_parse_client_version::parsed;
|
||||
}
|
||||
|
||||
|
||||
TEST(p2p_client_version, test_0)
|
||||
{
|
||||
ASSERT_TRUE(check_parse_client_version("10.101.999.28391[deadbeef31337-dirty]", 10, 101, 999, 28391, "deadbeef31337", true));
|
||||
ASSERT_EQ(check_parse_client_version("10.101.999.28391[deadbeef31337-dirty]", 10, 101, 999, 28391, "deadbeef31337", true), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("+67.+43.+50.+83", 67, 43, 50, 83, "", false), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("-12.-90.17.-95", -12, -90, 17, -95, "", false), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("54.-100.-76.21[]", 54, -100, -76, 21, "", false), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("-93.8.-81.75[-dirty]", -93, 8, -81, 75, "", true), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("-8.-85.79.24[--dirty]", -8, -85, 79, 24, "-", true), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("-62.53.79.80[\\]", -62, 53, 79, 80, "\\", false), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("-27.91.-12.34[-]", -27, 91, -12, 34, "-", false), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("-51.-66.-10.58\0[--dirty]", -51, -66, -10, 58, "", false), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("-24.27.-81.79[" "\0" "-dirty]", {}, {}, {}, {}, {}, {}), reponse_check_parse_client_version::not_parsed);
|
||||
ASSERT_EQ(check_parse_client_version("0.0.0.0", 0, 0, 0, 0, "", false), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("27 . 33 . -59 . 47", 27, 33, -59, 47, "", false), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("-2147483648.-2147483648.-2147483648.-2147483648", INT32_MIN, INT32_MIN, INT32_MIN, INT32_MIN, "", false), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("2147483647.2147483647.2147483647.2147483647", INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, "", false), reponse_check_parse_client_version::parsed);
|
||||
//ASSERT_EQ(check_parse_client_version("2147483648.2147483648.2147483648.2147483648", INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, "", false), reponse_check_parse_client_version::parsed);
|
||||
//ASSERT_EQ(check_parse_client_version("-2147483649.-2147483649.-2147483649.-2147483649", INT32_MIN, INT32_MIN, INT32_MIN, INT32_MIN, "", false), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("0098.+0096.0081.-0056", 98, 96, 81, -56, "", false), reponse_check_parse_client_version::parsed);
|
||||
ASSERT_EQ(check_parse_client_version("\0" "38.67.31.-24", 38, 67, 31, -24, "", false), reponse_check_parse_client_version::not_parsed);
|
||||
ASSERT_EQ(check_parse_client_version({'-', '6', '8', '.', '\0', '2', '9', '.', '5', '9', '.', '-', '7', '9'}, {}, {}, {}, {}, {}, {}), reponse_check_parse_client_version::not_parsed);
|
||||
ASSERT_EQ(check_parse_client_version("....", {}, {}, {}, {}, {}, {}), reponse_check_parse_client_version::not_parsed);
|
||||
ASSERT_EQ(check_parse_client_version("54.12.-10", {}, {}, {}, {}, {}, {}), reponse_check_parse_client_version::not_parsed);
|
||||
ASSERT_EQ(check_parse_client_version("-.-.-.-", {}, {}, {}, {}, {}, {}), reponse_check_parse_client_version::not_parsed);
|
||||
ASSERT_EQ(check_parse_client_version(" . . . ", {}, {}, {}, {}, {}, {}), reponse_check_parse_client_version::not_parsed);
|
||||
|
||||
ASSERT_EQ(check_parse_client_version({'-', '2', '3', '.', '6', '.', '-', '1', '8', '.', '-', '1', '1', '[', '\0', ']'}, -23, 6, -18, -11, std::string{'\0'}, false),
|
||||
reponse_check_parse_client_version::parsed);
|
||||
|
||||
ASSERT_EQ(check_parse_client_version({'9', '8', '.', '3', '.', '8', '9', '.', '-', '1', '[', '\0', '-', 'd', 'i','r', 't', 'y', ']'}, 98, 3, 89, -1, std::string{'\0'}, true),
|
||||
reponse_check_parse_client_version::parsed);
|
||||
|
||||
//ASSERT_EQ(check_parse_client_version("5.42.25.-42[].", 5, 42, 25, -42, "", false), reponse_check_parse_client_version::parsed);
|
||||
//ASSERT_EQ(check_parse_client_version("-84.91.-10.1[-dirty].", 5, 42, 25, -42, "", true), reponse_check_parse_client_version::parsed);
|
||||
//ASSERT_EQ(check_parse_client_version("33.62.-92.-44.", 33, 62, -92, -44, "", false), reponse_check_parse_client_version::parsed);
|
||||
//ASSERT_EQ(check_parse_client_version("...", {}, {}, {}, {}, {}, {}), reponse_check_parse_client_version::not_parsed);
|
||||
//ASSERT_EQ(check_parse_client_version("-80.28.-6.1[", -80, 28, -6, 1, "", false), reponse_check_parse_client_version::parsed);
|
||||
//ASSERT_EQ(check_parse_client_version("-88.-36.11.-25[", -80, 28, -6, 1, "", false), reponse_check_parse_client_version::parsed);
|
||||
//ASSERT_EQ(check_parse_client_version("0.0.0.[]", {}, {}, {}, {}, {}, {}), reponse_check_parse_client_version::not_parsed);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
139
tests/unit_tests/prepare_outputs_entries_for_key_offsets.cpp
Normal file
139
tests/unit_tests/prepare_outputs_entries_for_key_offsets.cpp
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "currency_core/currency_format_utils_abstract.h"
|
||||
#include "currency_core/currency_format_utils_transactions.h"
|
||||
|
||||
TEST(prepare_outputs_for_key_offsets, size_lower_than_2)
|
||||
{
|
||||
for (size_t size{}; size < 2; ++size)
|
||||
{
|
||||
std::vector<currency::tx_source_entry::output_entry> outputs(size);
|
||||
size_t index{SIZE_MAX};
|
||||
|
||||
ASSERT_EQ(currency::prepare_outputs_entries_for_key_offsets(outputs, 0, index), outputs);
|
||||
ASSERT_EQ(index, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(prepare_outputs_for_key_offsets, pass_index_greater_or_equal_to_length_of_outputs_container)
|
||||
{
|
||||
const std::vector<currency::tx_source_entry::output_entry> outputs(2);
|
||||
|
||||
{
|
||||
auto index{crypto::rand<size_t>()};
|
||||
const auto index_before_preparing_outputs{index};
|
||||
|
||||
ASSERT_TRUE(currency::prepare_outputs_entries_for_key_offsets(outputs, outputs.size(), index).empty());
|
||||
ASSERT_EQ(index, index_before_preparing_outputs);
|
||||
}
|
||||
|
||||
{
|
||||
auto index{crypto::rand<size_t>()};
|
||||
const auto index_before_preparing_outputs{index};
|
||||
|
||||
ASSERT_TRUE(currency::prepare_outputs_entries_for_key_offsets(outputs, outputs.size() + 1, index).empty());
|
||||
ASSERT_EQ(index, index_before_preparing_outputs);
|
||||
}
|
||||
|
||||
{
|
||||
auto index{crypto::rand<size_t>()};
|
||||
const auto index_before_preparing_outputs{index};
|
||||
|
||||
ASSERT_TRUE(currency::prepare_outputs_entries_for_key_offsets(outputs, SIZE_MAX - 1, index).empty());
|
||||
ASSERT_EQ(index, index_before_preparing_outputs);
|
||||
}
|
||||
|
||||
{
|
||||
auto index{crypto::rand<size_t>()};
|
||||
const auto index_before_preparing_outputs{index};
|
||||
|
||||
ASSERT_EQ(currency::prepare_outputs_entries_for_key_offsets(outputs, SIZE_MAX, index), outputs);
|
||||
ASSERT_EQ(index, index_before_preparing_outputs);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(prepare_outputs_for_key_offsets, uint64_reference_lower_than_by_id_reference)
|
||||
{
|
||||
std::vector<currency::tx_source_entry::output_entry> outputs{}, expected_prepared_outputs{};
|
||||
size_t index{};
|
||||
|
||||
outputs.reserve(2);
|
||||
outputs.emplace_back(currency::ref_by_id{}, currency::null_pkey);
|
||||
outputs.emplace_back(0, currency::null_pkey);
|
||||
expected_prepared_outputs.reserve(outputs.size());
|
||||
expected_prepared_outputs.emplace_back(0, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(currency::ref_by_id{}, currency::null_pkey);
|
||||
ASSERT_EQ(outputs.size(), expected_prepared_outputs.size());
|
||||
ASSERT_EQ(currency::prepare_outputs_entries_for_key_offsets(outputs, 0, index), expected_prepared_outputs);
|
||||
ASSERT_EQ(index, 1);
|
||||
}
|
||||
|
||||
TEST(prepare_outputs_for_key_offsets, subsequence_of_ref_by_id_references_is_not_changed)
|
||||
{
|
||||
{
|
||||
std::vector<currency::tx_source_entry::output_entry> outputs{}, expected_prepared_outputs{};
|
||||
size_t index{};
|
||||
|
||||
outputs.reserve(6);
|
||||
outputs.emplace_back(3, currency::null_pkey);
|
||||
outputs.emplace_back(currency::ref_by_id{currency::null_hash, 1}, currency::null_pkey);
|
||||
outputs.emplace_back(currency::ref_by_id{currency::null_hash, 0}, currency::null_pkey);
|
||||
outputs.emplace_back(2, currency::null_pkey);
|
||||
outputs.emplace_back(currency::ref_by_id{currency::null_hash, 3}, currency::null_pkey);
|
||||
outputs.emplace_back(1, currency::null_pkey);
|
||||
expected_prepared_outputs.reserve(outputs.size());
|
||||
expected_prepared_outputs.emplace_back(1, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(1, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(1, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(currency::ref_by_id{currency::null_hash, 1}, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(currency::ref_by_id{currency::null_hash, 0}, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(currency::ref_by_id{currency::null_hash, 3}, currency::null_pkey);
|
||||
ASSERT_EQ(outputs.size(), expected_prepared_outputs.size());
|
||||
ASSERT_EQ(currency::prepare_outputs_entries_for_key_offsets(outputs, 0, index), expected_prepared_outputs);
|
||||
ASSERT_EQ(index, 2);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<currency::tx_source_entry::output_entry> outputs{}, expected_prepared_outputs{};
|
||||
size_t index{};
|
||||
|
||||
outputs.reserve(5);
|
||||
outputs.emplace_back(currency::ref_by_id{currency::null_hash, 1}, currency::null_pkey);
|
||||
outputs.emplace_back(currency::ref_by_id{currency::null_hash, 0}, currency::null_pkey);
|
||||
outputs.emplace_back(currency::ref_by_id{currency::null_hash, 3}, currency::null_pkey);
|
||||
outputs.emplace_back(1, currency::null_pkey);
|
||||
outputs.emplace_back(0, currency::null_pkey);
|
||||
expected_prepared_outputs.reserve(outputs.size());
|
||||
expected_prepared_outputs.emplace_back(0, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(1, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(currency::ref_by_id{currency::null_hash, 1}, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(currency::ref_by_id{currency::null_hash, 0}, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(currency::ref_by_id{currency::null_hash, 3}, currency::null_pkey);
|
||||
ASSERT_EQ(outputs.size(), expected_prepared_outputs.size());
|
||||
ASSERT_EQ(currency::prepare_outputs_entries_for_key_offsets(outputs, 0, index), expected_prepared_outputs);
|
||||
ASSERT_EQ(outputs.at(0), expected_prepared_outputs.at(2));
|
||||
ASSERT_EQ(index, 2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(prepare_outputs_for_key_offsets, index_will_not_be_changed_if_old_index_is_size_max)
|
||||
{
|
||||
std::vector<currency::tx_source_entry::output_entry> outputs{}, expected_prepared_outputs{};
|
||||
auto index{crypto::rand<size_t>()};
|
||||
const auto index_before_preparing_outputs{index};
|
||||
|
||||
outputs.reserve(5);
|
||||
outputs.emplace_back(currency::ref_by_id{currency::null_hash, 1}, currency::null_pkey);
|
||||
outputs.emplace_back(currency::ref_by_id{currency::null_hash, 0}, currency::null_pkey);
|
||||
outputs.emplace_back(currency::ref_by_id{currency::null_hash, 3}, currency::null_pkey);
|
||||
outputs.emplace_back(1, currency::null_pkey);
|
||||
outputs.emplace_back(0, currency::null_pkey);
|
||||
expected_prepared_outputs.reserve(outputs.size());
|
||||
expected_prepared_outputs.emplace_back(0, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(1, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(currency::ref_by_id{currency::null_hash, 1}, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(currency::ref_by_id{currency::null_hash, 0}, currency::null_pkey);
|
||||
expected_prepared_outputs.emplace_back(currency::ref_by_id{currency::null_hash, 3}, currency::null_pkey);
|
||||
ASSERT_EQ(outputs.size(), expected_prepared_outputs.size());
|
||||
ASSERT_EQ(currency::prepare_outputs_entries_for_key_offsets(outputs, SIZE_MAX, index), expected_prepared_outputs);
|
||||
ASSERT_EQ(index, index_before_preparing_outputs);
|
||||
}
|
||||
|
|
@ -26,10 +26,12 @@ struct Struct
|
|||
char blob[8];
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator <<(std::ostream& o, const currency::signature_v& v)
|
||||
namespace currency
|
||||
{
|
||||
return o;
|
||||
ostream& operator<<(ostream& stream, [[maybe_unused]] const currency::signature_v& signature)
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
|
|
@ -902,4 +904,4 @@ TEST(Serialization, versioning2)
|
|||
r = perform_test_ser_vers<A_v3>(a_3);
|
||||
ASSERT_TRUE(r);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,17 +158,18 @@ TEST(wallet_seed, basic_test)
|
|||
{
|
||||
//generate random password
|
||||
std::string pass = epee::string_tools::pod_to_hex(crypto::cn_fast_hash(&j, sizeof(j)));
|
||||
if (j!= 0 && j < 64)
|
||||
{
|
||||
pass.resize(j);
|
||||
}
|
||||
pass.resize(std::min(j, (size_t)40));
|
||||
|
||||
//get secured seed
|
||||
std::string secured_seed = acc.get_seed_phrase(pass);
|
||||
|
||||
//try to restore it without password(should fail)
|
||||
currency::account_base acc2;
|
||||
bool r_fail = acc2.restore_from_seed_phrase(secured_seed, "");
|
||||
ASSERT_EQ(r_fail, false);
|
||||
currency::account_base acc2{};
|
||||
if (!pass.empty())
|
||||
{
|
||||
//try to restore it without password(should fail)
|
||||
bool r_fail = acc2.restore_from_seed_phrase(secured_seed, "");
|
||||
ASSERT_EQ(r_fail, false);
|
||||
}
|
||||
|
||||
//try to restore it with wrong password
|
||||
bool r_fake_pass = acc2.restore_from_seed_phrase(secured_seed, "fake_password");
|
||||
|
|
@ -182,7 +183,8 @@ TEST(wallet_seed, basic_test)
|
|||
currency::account_base acc3;
|
||||
bool r_true_res = acc3.restore_from_seed_phrase(secured_seed, pass);
|
||||
ASSERT_EQ(true, r_true_res);
|
||||
ASSERT_EQ(true, acc3.get_keys() == acc.get_keys());
|
||||
r = acc3.get_keys() == acc.get_keys();
|
||||
ASSERT_TRUE(r);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue