1
0
Fork 0
forked from lthn/blockchain

Merge branch 'develop' into release

This commit is contained in:
sowle 2024-11-11 01:21:05 +01:00
commit c24d165627
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
74 changed files with 4183 additions and 2549 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1083,7 +1083,6 @@ namespace crypto
make_random();
}
}; // scalar_vec_t

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1340,7 +1340,6 @@ TEST(perf, point_eq_vs_iszero)
return true;
}
TEST(perf, buff_to_hex)
{
std::vector<std::string> in_buffs;

View file

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

View file

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

View file

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

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

View file

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

View file

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