forked from lthn/blockchain
Merge branch 'develop' into merge_develop_mobile
This commit is contained in:
commit
390adb3e26
48 changed files with 1753 additions and 557 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -5,4 +5,5 @@
|
|||
._.DS_Store
|
||||
Thumbs.db
|
||||
._*
|
||||
.idea
|
||||
.idea
|
||||
.vs/*
|
||||
|
|
@ -102,7 +102,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
|||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions("/D_CRT_SECURE_NO_WARNINGS /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /D__SSE4_1__")
|
||||
add_definitions("/D_CRT_SECURE_NO_WARNINGS /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0")
|
||||
add_compile_options(/bigobj /Zm1000 /Z7 /MP2 /W3 /GS- /wd4996 /wd4503 /wd4345 /wd4091 /FIinline_c.h)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:10485760 /DEBUG dbghelp.lib crypt32.lib")
|
||||
if(STATIC)
|
||||
|
|
@ -224,7 +224,7 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
|
|||
elseif(APPLE)
|
||||
find_package(Boost 1.71 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale)
|
||||
else()
|
||||
find_package(Boost 1.70 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale)
|
||||
find_package(Boost 1.70 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale log)
|
||||
endif()
|
||||
|
||||
|
||||
|
|
@ -246,7 +246,7 @@ elseif(NOT MSVC)
|
|||
endif()
|
||||
|
||||
if(BUILD_GUI)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ endif()
|
|||
set_property(TARGET upnpc-static mdbx_chk mdbx_copy mdbx_dump mdbx_load mdbx_stat PROPERTY FOLDER "unused")
|
||||
|
||||
if(MSVC)
|
||||
set_property(TARGET ntdll_extra_target PROPERTY FOLDER "unused")
|
||||
#set_property(TARGET ntdll_extra_target PROPERTY FOLDER "unused")
|
||||
endif()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -45,61 +45,6 @@ if(CC_HAS_VISIBILITY AND (LTO_ENABLED OR INTERPROCEDURAL_OPTIMIZATION))
|
|||
set_target_properties(mdbx PROPERTIES LINK_FLAGS "-fvisibility=hidden")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
if(MSVC)
|
||||
if(NOT MSVC_LIB_EXE)
|
||||
# Find lib.exe
|
||||
get_filename_component(CL_NAME ${CMAKE_C_COMPILER} NAME)
|
||||
string(REPLACE cl.exe lib.exe MSVC_LIB_EXE ${CL_NAME})
|
||||
find_program(MSVC_LIB_EXE ${MSVC_LIB_EXE})
|
||||
endif()
|
||||
if(MSVC_LIB_EXE)
|
||||
message(STATUS "Found MSVC's lib tool: ${MSVC_LIB_EXE}")
|
||||
set(MDBX_NTDLL_EXTRA_IMPLIB ${CMAKE_CURRENT_BINARY_DIR}/mdbx_ntdll_extra.lib)
|
||||
add_custom_command(OUTPUT ${MDBX_NTDLL_EXTRA_IMPLIB}
|
||||
COMMENT "Create extra-import-library for ntdll.dll"
|
||||
MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/elements/ntdll.def"
|
||||
COMMAND ${MSVC_LIB_EXE} /def:"${CMAKE_CURRENT_SOURCE_DIR}/elements/ntdll.def" /out:"${MDBX_NTDLL_EXTRA_IMPLIB}" ${INITIAL_CMAKE_STATIC_LINKER_FLAGS})
|
||||
else()
|
||||
message(SEND_ERROR "MSVC's lib tool not found")
|
||||
endif()
|
||||
elseif(MINGW OR MINGW64)
|
||||
if(NOT DLLTOOL)
|
||||
# Find dlltool
|
||||
get_filename_component(GCC_NAME ${CMAKE_C_COMPILER} NAME)
|
||||
string(REPLACE gcc dlltool DLLTOOL_NAME ${GCC_NAME})
|
||||
find_program(DLLTOOL NAMES ${DLLTOOL_NAME})
|
||||
endif()
|
||||
if(DLLTOOL)
|
||||
message(STATUS "Found dlltool: ${DLLTOOL}")
|
||||
set(MDBX_NTDLL_EXTRA_IMPLIB "${CMAKE_CURRENT_BINARY_DIR}/mdbx_ntdll_extra.a")
|
||||
add_custom_command(OUTPUT ${MDBX_NTDLL_EXTRA_IMPLIB}
|
||||
COMMENT "Create extra-import-library for ntdll.dll"
|
||||
MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/elements/ntdll.def"
|
||||
COMMAND ${DLLTOOL} -d "${CMAKE_CURRENT_SOURCE_DIR}/elements/ntdll.def" -l "${MDBX_NTDLL_EXTRA_IMPLIB}")
|
||||
else()
|
||||
message(SEND_ERROR "dlltool not found")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(mdbx ${MDBX_LIBDEP_MODE} ${CMAKE_THREAD_LIBS_INIT})
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
target_link_libraries(mdbx ${MDBX_LIBDEP_MODE} ntdll.lib)
|
||||
if(MDBX_NTDLL_EXTRA_IMPLIB)
|
||||
# LY: Sometimes Cmake requires a nightmarish magic for simple things.
|
||||
# 1) create a target out of the library compilation result
|
||||
add_custom_target(ntdll_extra_target DEPENDS ${MDBX_NTDLL_EXTRA_IMPLIB})
|
||||
# 2) create an library target out of the library compilation result
|
||||
add_library(ntdll_extra STATIC IMPORTED GLOBAL)
|
||||
add_dependencies(ntdll_extra ntdll_extra_target)
|
||||
# 3) specify where the library is (and where to find the headers)
|
||||
set_target_properties(ntdll_extra
|
||||
PROPERTIES
|
||||
IMPORTED_LOCATION ${MDBX_NTDLL_EXTRA_IMPLIB})
|
||||
target_link_libraries(mdbx ${MDBX_LIBDEP_MODE} ntdll_extra)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_target_properties(mdbx PROPERTIES
|
||||
INTERPROCEDURAL_OPTIMIZATION $<BOOL:${INTERPROCEDURAL_OPTIMIZATION}>
|
||||
|
|
|
|||
|
|
@ -509,6 +509,10 @@ namespace misc_utils
|
|||
}
|
||||
}
|
||||
|
||||
void UNSUBSCRIBE_ALL()
|
||||
{
|
||||
m_callbacks.clear();
|
||||
}
|
||||
|
||||
template<typename param_t>
|
||||
void RAISE_DEBUG_EVENT(const param_t& p)
|
||||
|
|
|
|||
|
|
@ -137,11 +137,17 @@ namespace tools
|
|||
|
||||
STACKFRAME64 frame;
|
||||
memset(&frame, 0, sizeof frame);
|
||||
#ifndef _M_ARM64
|
||||
frame.AddrPC.Offset = context.Rip;
|
||||
#endif
|
||||
frame.AddrPC.Mode = AddrModeFlat;
|
||||
#ifndef _M_ARM64
|
||||
frame.AddrStack.Offset = context.Rsp;
|
||||
#endif
|
||||
frame.AddrStack.Mode = AddrModeFlat;
|
||||
#ifndef _M_ARM64
|
||||
frame.AddrFrame.Offset = context.Rbp;
|
||||
#endif
|
||||
frame.AddrFrame.Mode = AddrModeFlat;
|
||||
|
||||
IMAGEHLP_LINE64 line = { 0 };
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ namespace command_line
|
|||
|
||||
const arg_descriptor<bool> arg_no_predownload ( "no-predownload", "Do not pre-download blockchain database");
|
||||
const arg_descriptor<bool> arg_force_predownload ( "force-predownload", "Pre-download blockchain database regardless of it's status");
|
||||
const arg_descriptor<std::string> arg_process_predownload_from_path("predownload-from-local-path", "Instead of downloading file use downloaded local file");
|
||||
const arg_descriptor<bool> arg_validate_predownload ( "validate-predownload", "Paranoid mode, re-validate each block from pre-downloaded database and rebuild own database");
|
||||
const arg_descriptor<std::string> arg_predownload_link ( "predownload-link", "Override url for blockchain database pre-downloading");
|
||||
|
||||
|
|
|
|||
|
|
@ -229,6 +229,7 @@ namespace command_line
|
|||
extern const arg_descriptor<std::string> arg_db_engine;
|
||||
extern const arg_descriptor<bool> arg_no_predownload;
|
||||
extern const arg_descriptor<bool> arg_force_predownload;
|
||||
extern const arg_descriptor<std::string> arg_process_predownload_from_path;
|
||||
extern const arg_descriptor<bool> arg_validate_predownload;
|
||||
extern const arg_descriptor<std::string> arg_predownload_link;
|
||||
extern const arg_descriptor<std::string> arg_deeplink;
|
||||
|
|
|
|||
|
|
@ -104,15 +104,15 @@ namespace crypto
|
|||
FIELD((std::vector<scalar_t>&)(r_x))
|
||||
FIELD(K1)
|
||||
FIELD(K2)
|
||||
END_SERIALIZE()
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(c)
|
||||
BOOST_SERIALIZE((std::vector<scalar_t>&)(r_g))
|
||||
BOOST_SERIALIZE((std::vector<scalar_t>&)(r_x))
|
||||
BOOST_SERIALIZE(K1)
|
||||
BOOST_SERIALIZE(K2)
|
||||
END_BOOST_SERIALIZATION()
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct CLSAG_GGXXG_signature_serialized : public CLSAG_GGXXG_signature
|
||||
|
|
@ -183,6 +183,21 @@ namespace crypto
|
|||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct generic_double_schnorr_sig_s : public generic_double_schnorr_sig
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(c)
|
||||
FIELD(y0)
|
||||
FIELD(y1)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(c)
|
||||
BOOST_SERIALIZE(y0)
|
||||
BOOST_SERIALIZE(y1)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
struct BGE_proof_s : public BGE_proof
|
||||
{
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ namespace tools
|
|||
};
|
||||
|
||||
#ifndef TESTNET
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.42.247/pre-download/zano_mdbx_95_2390000.pak", "ffc8d2220a4d8b3fba51073a422cbb6139c60858469ea086623f9d16329eb5b4", 2767268964, 5368627200 };
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.42.247/pre-download/zano_lmdb_95_2390000.pak", "7e58951bc523eb12e0ec07171bc67b3f96bad4d5454dd2da56f642a872e230d3", 3618283035, 5156397056 };
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.42.247/pre-download/zano_mdbx_95_2500000.pak", "8ffa2cb4213f4f96f97033c65a9e52bc350f683237808597784e79b24d5bfee7", 3242348793, 5905489920 };
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.42.247/pre-download/zano_lmdb_95_2500000.pak", "5509650e12c8f901e6731a2bfaf3abfd64409e3e1366d3d94cd11db8beddb0c3", 4239505801, 5893566464 };
|
||||
#else
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "", "", 0, 0 };
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "", "", 0, 0 };
|
||||
|
|
@ -50,6 +50,7 @@ namespace tools
|
|||
|
||||
boost::system::error_code ec;
|
||||
uint64_t sz = boost::filesystem::file_size(db_main_file_path, ec);
|
||||
if (ec) sz = 0;
|
||||
bool flag_force_predownload = command_line::has_arg(vm, command_line::arg_force_predownload);
|
||||
if (pre_download.unpacked_size == 0 || !(ec || (pre_download.unpacked_size > sz && pre_download.unpacked_size - sz > pre_download_min_size_difference) || flag_force_predownload) )
|
||||
{
|
||||
|
|
@ -59,53 +60,59 @@ namespace tools
|
|||
|
||||
// okay, let's download
|
||||
|
||||
|
||||
std::string downloading_file_path = db_main_file_path + ".download";
|
||||
|
||||
LOG_PRINT_MAGENTA("Trying to download blockchain database from " << url << " ...", LOG_LEVEL_0);
|
||||
epee::net_utils::http::interruptible_http_client cl;
|
||||
|
||||
crypto::stream_cn_hash hash_stream;
|
||||
auto last_update = std::chrono::system_clock::now();
|
||||
|
||||
auto cb = [&hash_stream, &last_update, &cb_should_stop](const std::string& buff, uint64_t total_bytes, uint64_t received_bytes)
|
||||
if (!command_line::has_arg(vm, command_line::arg_process_predownload_from_path))
|
||||
{
|
||||
if (cb_should_stop(total_bytes, received_bytes))
|
||||
|
||||
LOG_PRINT_MAGENTA("Trying to download blockchain database from " << url << " ...", LOG_LEVEL_0);
|
||||
epee::net_utils::http::interruptible_http_client cl;
|
||||
|
||||
crypto::stream_cn_hash hash_stream;
|
||||
auto last_update = std::chrono::system_clock::now();
|
||||
|
||||
auto cb = [&hash_stream, &last_update, &cb_should_stop](const std::string& buff, uint64_t total_bytes, uint64_t received_bytes)
|
||||
{
|
||||
LOG_PRINT_MAGENTA(ENDL << "Interrupting download", LOG_LEVEL_0);
|
||||
return false;
|
||||
if (cb_should_stop(total_bytes, received_bytes))
|
||||
{
|
||||
LOG_PRINT_MAGENTA(ENDL << "Interrupting download", LOG_LEVEL_0);
|
||||
return false;
|
||||
}
|
||||
|
||||
hash_stream.update(buff.data(), buff.size());
|
||||
|
||||
auto dif = std::chrono::system_clock::now() - last_update;
|
||||
if (dif >= std::chrono::milliseconds(300))
|
||||
{
|
||||
boost::io::ios_flags_saver ifs(std::cout);
|
||||
std::cout << "Received " << received_bytes / 1048576 << " of " << total_bytes / 1048576 << " MiB ( " << std::fixed << std::setprecision(1) << 100.0 * received_bytes / total_bytes << " %)\r";
|
||||
last_update = std::chrono::system_clock::now();
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
tools::create_directories_if_necessary(working_folder);
|
||||
r = cl.download_and_unzip(cb, downloading_file_path, url, 5000 /* timout */, "GET", std::string(), 30 /* fails count */);
|
||||
if (!r)
|
||||
{
|
||||
LOG_PRINT_RED("Downloading failed", LOG_LEVEL_0);
|
||||
return !flag_force_predownload; // fatal error only if force-predownload
|
||||
}
|
||||
|
||||
hash_stream.update(buff.data(), buff.size());
|
||||
|
||||
auto dif = std::chrono::system_clock::now() - last_update;
|
||||
if (dif >= std::chrono::milliseconds(300))
|
||||
crypto::hash data_hash = hash_stream.calculate_hash();
|
||||
if (epee::string_tools::pod_to_hex(data_hash) != pre_download.hash)
|
||||
{
|
||||
boost::io::ios_flags_saver ifs(std::cout);
|
||||
std::cout << "Received " << received_bytes / 1048576 << " of " << total_bytes / 1048576 << " MiB ( " << std::fixed << std::setprecision(1) << 100.0 * received_bytes / total_bytes << " %)\r";
|
||||
last_update = std::chrono::system_clock::now();
|
||||
LOG_ERROR("hash missmatch in downloaded file, got: " << epee::string_tools::pod_to_hex(data_hash) << ", expected: " << pre_download.hash);
|
||||
return !flag_force_predownload; // fatal error only if force-predownload
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
tools::create_directories_if_necessary(working_folder);
|
||||
r = cl.download_and_unzip(cb, downloading_file_path, url, 5000 /* timout */, "GET", std::string(), 30 /* fails count */);
|
||||
if (!r)
|
||||
{
|
||||
LOG_PRINT_RED("Downloading failed", LOG_LEVEL_0);
|
||||
return !flag_force_predownload; // fatal error only if force-predownload
|
||||
LOG_PRINT_GREEN("Download succeeded, hash " << pre_download.hash << " is correct", LOG_LEVEL_0);
|
||||
}
|
||||
|
||||
crypto::hash data_hash = hash_stream.calculate_hash();
|
||||
if (epee::string_tools::pod_to_hex(data_hash) != pre_download.hash)
|
||||
else
|
||||
{
|
||||
LOG_ERROR("hash missmatch in downloaded file, got: " << epee::string_tools::pod_to_hex(data_hash) << ", expected: " << pre_download.hash);
|
||||
return !flag_force_predownload; // fatal error only if force-predownload
|
||||
downloading_file_path = command_line::get_arg(vm, command_line::arg_process_predownload_from_path);
|
||||
}
|
||||
|
||||
LOG_PRINT_GREEN("Download succeeded, hash " << pre_download.hash << " is correct" , LOG_LEVEL_0);
|
||||
|
||||
if (!command_line::has_arg(vm, command_line::arg_validate_predownload))
|
||||
{
|
||||
boost::filesystem::remove(db_main_file_path, ec);
|
||||
|
|
@ -138,11 +145,14 @@ namespace tools
|
|||
std::string path_to_temp_blockchain_file = path_to_temp_blockchain + "/" + dbbs.get_db_main_file_name();
|
||||
|
||||
tools::create_directories_if_necessary(path_to_temp_blockchain);
|
||||
boost::filesystem::rename(downloading_file_path, path_to_temp_blockchain_file, ec);
|
||||
if (ec)
|
||||
if (downloading_file_path != path_to_temp_blockchain_file)
|
||||
{
|
||||
LOG_ERROR("Rename failed: " << downloading_file_path << " -> " << path_to_temp_blockchain_file);
|
||||
return false;
|
||||
boost::filesystem::rename(downloading_file_path, path_to_temp_blockchain_file, ec);
|
||||
if (ec)
|
||||
{
|
||||
LOG_ERROR("Rename failed: " << downloading_file_path << " -> " << path_to_temp_blockchain_file);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// remove old blockchain database from disk
|
||||
|
|
@ -180,6 +190,28 @@ namespace tools
|
|||
r = target_core.init(target_core_vm);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to init target core");
|
||||
|
||||
if (true/*TODO: copnfigure with command line option*/)
|
||||
{
|
||||
//set checkpoints
|
||||
{
|
||||
currency::checkpoints checkpoints;
|
||||
bool res = currency::create_checkpoints(checkpoints);
|
||||
CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize checkpoints");
|
||||
res = source_core.set_checkpoints(std::move(checkpoints));
|
||||
CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize core");
|
||||
}
|
||||
{
|
||||
currency::checkpoints checkpoints;
|
||||
bool res = currency::create_checkpoints(checkpoints);
|
||||
CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize checkpoints");
|
||||
res = target_core.set_checkpoints(std::move(checkpoints));
|
||||
CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize core");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
CHECK_AND_ASSERT_MES(target_core.get_top_block_height() == 0, false, "Target blockchain initialized not empty");
|
||||
uint64_t total_blocks = source_core.get_current_blockchain_size();
|
||||
|
||||
|
|
|
|||
|
|
@ -411,7 +411,8 @@ bool generate_genesis(const std::string& path_config, uint64_t premine_split_amo
|
|||
|
||||
std::cout << ENDL << "PROOF PHRASE: " << gcp.proof_string << ENDL;
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
construct_miner_tx(0, 0, 0, 0, 0, dummy_address, dummy_address, bl.miner_tx, block_reward_without_fee, TRANSACTION_VERSION_PRE_HF4, gcp.proof_string, CURRENCY_MINER_TX_MAX_OUTS, false, pos_entry(), nullptr, nullptr, destinations);
|
||||
uint64_t block_reward = 0;
|
||||
construct_miner_tx(0, 0, 0, 0, 0, dummy_address, dummy_address, bl.miner_tx, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, gcp.proof_string, CURRENCY_MINER_TX_MAX_OUTS, false, pos_entry(), nullptr, nullptr, destinations);
|
||||
currency::blobdata txb = tx_to_blob(bl.miner_tx);
|
||||
|
||||
//self validate block
|
||||
|
|
|
|||
|
|
@ -1166,6 +1166,11 @@ namespace crypto
|
|||
return scalar_t(crypto::cn_fast_hash(str.c_str(), str.size())); // will reduce mod L
|
||||
}
|
||||
|
||||
static hash h(const std::string& str)
|
||||
{
|
||||
return crypto::cn_fast_hash(str.c_str(), str.size());
|
||||
}
|
||||
|
||||
struct hs_t
|
||||
{
|
||||
hs_t(size_t size_to_reserve = 0)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "hash-ops.h"
|
||||
|
||||
#ifdef _M_ARM64
|
||||
#include "malloc.h"
|
||||
#endif
|
||||
void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash) {
|
||||
assert(count > 0);
|
||||
if (count == 1) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2022-2023 Zano Project
|
||||
// Copyright (c) 2022-2023 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Copyright (c) 2022-2024 Zano Project
|
||||
// Copyright (c) 2022-2024 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
|
|
@ -84,46 +84,47 @@ namespace crypto
|
|||
scalar_t y;
|
||||
};
|
||||
|
||||
template<generator_tag gen>
|
||||
|
||||
template<typename generator_t>
|
||||
inline bool generate_schnorr_sig_custom_generator(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result, const generator_t& g_point_g)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (A != secret_a * g_point_g)
|
||||
return false;
|
||||
#endif
|
||||
scalar_t r = scalar_t::random();
|
||||
point_t R = r * g_point_g;
|
||||
hash_helper_t::hs_t hsc(3);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_point(R);
|
||||
result.c = hsc.calc_hash();
|
||||
result.y.assign_mulsub(result.c, secret_a, r); // y = r - c * secret_a
|
||||
return true;
|
||||
}
|
||||
|
||||
template<generator_tag gen = gt_G>
|
||||
inline bool generate_schnorr_sig(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result);
|
||||
|
||||
template<>
|
||||
inline bool generate_schnorr_sig<gt_G>(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (A != secret_a * c_point_G)
|
||||
return false;
|
||||
#endif
|
||||
scalar_t r = scalar_t::random();
|
||||
point_t R = r * c_point_G;
|
||||
hash_helper_t::hs_t hsc(3);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_point(R);
|
||||
result.c = hsc.calc_hash();
|
||||
result.y.assign_mulsub(result.c, secret_a, r); // y = r - c * secret_a
|
||||
return true;
|
||||
return generate_schnorr_sig_custom_generator(m, A, secret_a, result, c_point_G);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool generate_schnorr_sig<gt_X>(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (A != secret_a * c_point_X)
|
||||
return false;
|
||||
#endif
|
||||
scalar_t r = scalar_t::random();
|
||||
point_t R = r * c_point_X;
|
||||
hash_helper_t::hs_t hsc(3);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_point(R);
|
||||
result.c = hsc.calc_hash();
|
||||
result.y.assign_mulsub(result.c, secret_a, r); // y = r - c * secret_a
|
||||
return true;
|
||||
return generate_schnorr_sig_custom_generator(m, A, secret_a, result, c_point_X);
|
||||
}
|
||||
|
||||
template<generator_tag gen>
|
||||
inline bool generate_schnorr_sig(const hash& m, const public_key& A, const secret_key& secret_a, generic_schnorr_sig& result)
|
||||
{
|
||||
return generate_schnorr_sig(m, point_t(A), scalar_t(secret_a), result);
|
||||
}
|
||||
|
||||
|
||||
template<generator_tag gen = gt_G>
|
||||
inline bool verify_schnorr_sig(const hash& m, const public_key& A, const generic_schnorr_sig& sig) noexcept;
|
||||
|
||||
// TODO @#@# make optimized version inline bool verify_schnorr_sig(const hash& m, const point_t& A, const generic_schnorr_sig& sig) noexcept;
|
||||
|
|
@ -167,6 +168,110 @@ namespace crypto
|
|||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------
|
||||
|
||||
// multi-base Schnorr-like proof (two generators, two secrets, one Fiat-Shamir challenge)
|
||||
struct generic_double_schnorr_sig
|
||||
{
|
||||
scalar_t c;
|
||||
scalar_t y0;
|
||||
scalar_t y1;
|
||||
};
|
||||
|
||||
template<generator_tag gen0, generator_tag gen1>
|
||||
inline bool generate_double_schnorr_sig(const hash& m, const point_t& A, const scalar_t& secret_a, const point_t& B, const scalar_t& secret_b, generic_double_schnorr_sig& result);
|
||||
|
||||
template<>
|
||||
inline bool generate_double_schnorr_sig<gt_G, gt_G>(const hash& m, const point_t& A, const scalar_t& secret_a, const point_t& B, const scalar_t& secret_b, generic_double_schnorr_sig& result)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (A != secret_a * c_point_G || B != secret_b * c_point_G)
|
||||
return false;
|
||||
#endif
|
||||
scalar_t r0 = scalar_t::random();
|
||||
scalar_t r1 = scalar_t::random();
|
||||
point_t R0 = r0 * c_point_G;
|
||||
point_t R1 = r1 * c_point_G;
|
||||
hash_helper_t::hs_t hsc(5);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_point(B);
|
||||
hsc.add_point(R0);
|
||||
hsc.add_point(R1);
|
||||
result.c = hsc.calc_hash();
|
||||
result.y0.assign_mulsub(result.c, secret_a, r0); // y0 = r0 - c * secret_a
|
||||
result.y1.assign_mulsub(result.c, secret_b, r1); // y1 = r1 - c * secret_b
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool generate_double_schnorr_sig<gt_X, gt_G>(const hash& m, const point_t& A, const scalar_t& secret_a, const point_t& B, const scalar_t& secret_b, generic_double_schnorr_sig& result)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (A != secret_a * c_point_X || B != secret_b * c_point_G)
|
||||
return false;
|
||||
#endif
|
||||
scalar_t r0 = scalar_t::random();
|
||||
scalar_t r1 = scalar_t::random();
|
||||
point_t R0 = r0 * c_point_X;
|
||||
point_t R1 = r1 * c_point_G;
|
||||
hash_helper_t::hs_t hsc(5);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_point(B);
|
||||
hsc.add_point(R0);
|
||||
hsc.add_point(R1);
|
||||
result.c = hsc.calc_hash();
|
||||
result.y0.assign_mulsub(result.c, secret_a, r0); // y0 = r0 - c * secret_a
|
||||
result.y1.assign_mulsub(result.c, secret_b, r1); // y1 = r1 - c * secret_b
|
||||
return true;
|
||||
}
|
||||
|
||||
template<generator_tag gen0, generator_tag gen1>
|
||||
inline bool verify_double_schnorr_sig(const hash& m, const point_t& A, const public_key& B, const generic_double_schnorr_sig& sig) noexcept;
|
||||
|
||||
template<>
|
||||
inline bool verify_double_schnorr_sig<gt_G, gt_G>(const hash& m, const point_t& A, const public_key& B, const generic_double_schnorr_sig& sig) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!sig.c.is_reduced() || !sig.y0.is_reduced() || !sig.y1.is_reduced())
|
||||
return false;
|
||||
hash_helper_t::hs_t hsc(5);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_pub_key(B);
|
||||
hsc.add_point(A.mul_plus_G(sig.c, sig.y0)); // sig.y0 * G + sig.c * A
|
||||
hsc.add_point(point_t(B).mul_plus_G(sig.c, sig.y1)); // sig.y1 * G + sig.c * B
|
||||
return sig.c == hsc.calc_hash();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool verify_double_schnorr_sig<gt_X, gt_G>(const hash& m, const point_t& A, const public_key& B, const generic_double_schnorr_sig& sig) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!sig.c.is_reduced() || !sig.y0.is_reduced() || !sig.y1.is_reduced())
|
||||
return false;
|
||||
hash_helper_t::hs_t hsc(5);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_pub_key(B);
|
||||
hsc.add_point(sig.y0 * c_point_X + sig.c * A);
|
||||
hsc.add_point(point_t(B).mul_plus_G(sig.c, sig.y1)); // sig.y1 * G + sig.c * B
|
||||
return sig.c == hsc.calc_hash();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: improve this proof using random weightning factor
|
||||
struct vector_UG_aggregation_proof
|
||||
|
|
@ -187,4 +292,4 @@ namespace crypto
|
|||
const vector_UG_aggregation_proof& sig, uint8_t* p_err = nullptr) noexcept;
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
} // namespace crypto
|
||||
|
|
@ -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.
|
||||
|
|
@ -8,14 +8,54 @@
|
|||
|
||||
namespace bc_services
|
||||
{
|
||||
template<typename T>
|
||||
struct is_boost_variant : std::false_type {};
|
||||
|
||||
template<typename... Args>
|
||||
struct is_boost_variant<boost::variant<Args...>> : std::true_type {};
|
||||
|
||||
template<bool is_variant>
|
||||
struct type_selector;
|
||||
|
||||
template<>
|
||||
struct type_selector<true>
|
||||
{
|
||||
template<typename t_type>
|
||||
static const std::type_info& get_type(const t_type& t)
|
||||
{
|
||||
return t.type();
|
||||
}
|
||||
template<typename t_type, typename t_return_type>
|
||||
static const t_return_type& get(const t_type& t)
|
||||
{
|
||||
return boost::get<t_return_type>(t);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct type_selector<false>
|
||||
{
|
||||
template<typename t_type>
|
||||
static const std::type_info& get_type(const t_type& t)
|
||||
{
|
||||
return typeid(t);
|
||||
}
|
||||
template<typename t_type, typename t_return_type>
|
||||
static const t_return_type& get(const t_type& t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
};
|
||||
|
||||
template<class t_attachment_type_container_t>
|
||||
bool get_first_service_attachment_by_id(const t_attachment_type_container_t& tx_items, const std::string& id, const std::string& instruction, currency::tx_service_attachment& res)
|
||||
{
|
||||
for (const auto& item : tx_items)
|
||||
{
|
||||
if (item.type() == typeid(currency::tx_service_attachment))
|
||||
typedef type_selector<is_boost_variant<typename t_attachment_type_container_t::value_type>::value> TS;
|
||||
if (TS::get_type(item) == typeid(currency::tx_service_attachment))
|
||||
{
|
||||
const currency::tx_service_attachment& tsa = boost::get<currency::tx_service_attachment>(item);
|
||||
const currency::tx_service_attachment& tsa = TS::template get<decltype(item), currency::tx_service_attachment>(item);
|
||||
if (tsa.service_id == id && tsa.instruction == instruction)
|
||||
{
|
||||
res = tsa;
|
||||
|
|
@ -25,4 +65,5 @@ namespace bc_services
|
|||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3161,7 +3161,7 @@ bool blockchain_storage::get_pos_votes(uint64_t start_index, uint64_t end_index,
|
|||
summary[v.first].no++;
|
||||
}
|
||||
}
|
||||
for (const auto s_entry : summary)
|
||||
for (const auto& s_entry : summary)
|
||||
{
|
||||
r.votes.push_back(s_entry.second);
|
||||
r.votes.back().proposal_id = s_entry.first;
|
||||
|
|
@ -3828,14 +3828,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;
|
||||
if (ei.m_asset_operation.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
|
||||
{
|
||||
calculate_asset_id(ei.m_asset_operation.descriptor.owner, nullptr, &asset_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_AND_NO_ASSERT_MES(false, false, "asset operation not implemented");
|
||||
}
|
||||
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);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to pop_alias_info");
|
||||
}
|
||||
|
|
@ -4086,15 +4079,14 @@ bool blockchain_storage::pop_asset_info(const crypto::public_key& asset_id)
|
|||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::validate_ado_ownership(asset_op_verification_context& avc)
|
||||
{
|
||||
// asset_id = AUTO_VAL_INIT(asset_id);
|
||||
// CHECK_AND_ASSERT_MES(validate_asset_operation_balance_proof(tx, tx_id, ado, asset_id), false, "asset operation validation failed!");
|
||||
CHECK_AND_ASSERT_MES(avc.ado.opt_proof.has_value(), false, "Ownership validation failed - missing signature");
|
||||
|
||||
asset_operation_ownership_proof aoop = AUTO_VAL_INIT(aoop);
|
||||
bool r = get_type_in_variant_container(avc.tx.proofs, aoop);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Ownership validation failed - missing signature (asset_operation_ownership_proof)");
|
||||
|
||||
CHECK_AND_ASSERT_MES(avc.asset_op_history->size() != 0, false, "asset with id " << avc.asset_id << " has invalid history size() == 0");
|
||||
|
||||
crypto::public_key owner_key = avc.asset_op_history->back().descriptor.owner;
|
||||
return crypto::check_signature(get_signature_hash_for_asset_operation(avc.ado), owner_key, *avc.ado.opt_proof);
|
||||
return crypto::verify_schnorr_sig(avc.tx_id, owner_key, aoop.gss);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado)
|
||||
|
|
@ -4105,12 +4097,13 @@ bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::has
|
|||
|
||||
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
|
||||
{
|
||||
calculate_asset_id(avc.ado.descriptor.owner, &avc.asset_id_pt, &avc.asset_id);
|
||||
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);
|
||||
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;
|
||||
CHECK_AND_ASSERT_MES(validate_asset_operation_amount_proof(avc), false, "asset operation validation failed!");
|
||||
CHECK_AND_ASSERT_MES(validate_asset_operation_amount_commitment(avc), false, "asset operation validation failed!");
|
||||
|
||||
assets_container::t_value_type local_asset_history = AUTO_VAL_INIT(local_asset_history);
|
||||
local_asset_history.push_back(ado);
|
||||
|
|
@ -4119,14 +4112,12 @@ bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::has
|
|||
}
|
||||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(avc.ado.opt_asset_id, false, "asset_id not provided for asset altering operation");
|
||||
avc.asset_op_history = m_db_assets.find(*avc.ado.opt_asset_id);
|
||||
avc.asset_id = *avc.ado.opt_asset_id; // consider redisign
|
||||
avc.asset_id_pt.from_public_key(avc.asset_id);
|
||||
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);
|
||||
|
||||
CHECK_AND_ASSERT_MES(avc.asset_op_history && avc.asset_op_history->size(), false, "asset with id " << avc.asset_id << " has not been registered");
|
||||
// check ownership permission
|
||||
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
|
||||
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE /*|| ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN*/)
|
||||
{
|
||||
bool r = validate_ado_ownership(avc);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Faild to validate ownership of asset_descriptor_operation, rejecting");
|
||||
|
|
@ -4157,19 +4148,19 @@ bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::has
|
|||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("Unknown operation type: " << ado.operation_type);
|
||||
LOG_ERROR("Unknown operation type: " << (int)ado.operation_type);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (need_to_validate_balance_proof)
|
||||
{
|
||||
bool r = validate_asset_operation_amount_proof(avc);
|
||||
bool r = validate_asset_operation_amount_commitment(avc);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Balance proof validation failed for asset_descriptor_operation");
|
||||
}
|
||||
|
||||
assets_container::t_value_type local_asset_history = *avc.asset_op_history;
|
||||
local_asset_history.push_back(ado);
|
||||
m_db_assets.set(*avc.ado.opt_asset_id, local_asset_history);
|
||||
m_db_assets.set(avc.asset_id, local_asset_history);
|
||||
|
||||
switch(ado.operation_type)
|
||||
{
|
||||
|
|
@ -4183,7 +4174,7 @@ bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::has
|
|||
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: " << ado.operation_type);
|
||||
LOG_ERROR("Unknown operation type: " << (int)ado.operation_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5816,7 +5807,7 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti
|
|||
};
|
||||
|
||||
//inputs
|
||||
for (const auto in : tx.vin)
|
||||
for (const auto& in : tx.vin)
|
||||
{
|
||||
if (!var_is_after_hardfork_1_zone && !is_allowed_before_hardfork1(in))
|
||||
return false;
|
||||
|
|
@ -5830,7 +5821,7 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti
|
|||
return false;
|
||||
}
|
||||
//outputs
|
||||
for (const auto out : tx.vout)
|
||||
for (const auto& out : tx.vout)
|
||||
{
|
||||
if (!var_is_after_hardfork_1_zone && !is_allowed_before_hardfork1(out))
|
||||
return false;
|
||||
|
|
@ -5846,7 +5837,7 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti
|
|||
|
||||
size_t count_ado = 0;
|
||||
//extra
|
||||
for (const auto el : tx.extra)
|
||||
for (const auto& el : tx.extra)
|
||||
{
|
||||
if (el.type() == typeid(asset_descriptor_operation))
|
||||
count_ado++;
|
||||
|
|
@ -5861,7 +5852,7 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti
|
|||
}
|
||||
|
||||
//attachments
|
||||
for (const auto el : tx.attachment)
|
||||
for (const auto& el : tx.attachment)
|
||||
{
|
||||
if (!var_is_after_hardfork_2_zone && !is_allowed_before_hardfork2(el))
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ namespace currency
|
|||
ADD_CHECKPOINT(1161000, "96990d851b484e30190678756ba2a4d3a2f92b987e2470728ac1e38b2bf35908");
|
||||
ADD_CHECKPOINT(1480000, "5dd3381eec35e8b4eba4518bfd8eec682a4292761d92218fd59b9f0ffedad3fe");
|
||||
ADD_CHECKPOINT(2000000, "7b6698a8cc279aa78d6263f01fef186bd16f5b1ea263a7f4714abc1d506b9cb3");
|
||||
ADD_CHECKPOINT(2390000, "10797d34349d0ef1d1ab4b41ada6f8f2c2f86a7f7eebe44dd2ba06067cb47e0a");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -438,18 +438,21 @@ namespace currency
|
|||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
// 1) for txs without ZC inputs: proves that balance point = lin(G) (cancels out G component of outputs' amount commitments, asset tags assumed to be H (native coin) and non-blinded)
|
||||
// 2) for txs with ZC inputs: proves that balance point = lin(X) (cancels out X component of blinded asset tags within amount commitments for both outputs and inputs (pseudo outs))
|
||||
// First part of a double Schnorr proof:
|
||||
// 1) for txs without ZC inputs: proves that balance point = lin(G) (cancels out G component of outputs' amount commitments, asset tags assumed to be H (native coin) and non-blinded)
|
||||
// 2) for txs with ZC inputs: proves that balance point = lin(X) (cancels out X component of blinded asset tags within amount commitments for both outputs and inputs (pseudo outs))
|
||||
// Second part:
|
||||
// proof of knowing transaction secret key (with respect to G)
|
||||
struct zc_balance_proof
|
||||
{
|
||||
crypto::generic_schnorr_sig_s ss;
|
||||
crypto::generic_double_schnorr_sig_s dss;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(ss)
|
||||
FIELD(dss)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(ss)
|
||||
BOOST_SERIALIZE(dss)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
|
|
@ -772,7 +775,6 @@ namespace currency
|
|||
uint8_t operation_type = ASSET_DESCRIPTOR_OPERATION_UNDEFINED;
|
||||
asset_descriptor_base descriptor;
|
||||
crypto::public_key amount_commitment; // premultiplied by 1/8
|
||||
boost::optional<crypto::signature> opt_proof; // operation proof - for update/emit
|
||||
boost::optional<crypto::public_key> opt_asset_id; // target asset_id - for update/emit
|
||||
uint8_t verion = ASSET_DESCRIPTOR_OPERATION_STRUCTURE_VER;
|
||||
|
||||
|
|
@ -781,7 +783,6 @@ namespace currency
|
|||
FIELD(descriptor)
|
||||
FIELD(amount_commitment)
|
||||
END_VERSION_UNDER(1)
|
||||
FIELD(opt_proof)
|
||||
FIELD(opt_asset_id)
|
||||
END_SERIALIZE()
|
||||
|
||||
|
|
@ -790,7 +791,6 @@ namespace currency
|
|||
BOOST_SERIALIZE(descriptor)
|
||||
BOOST_SERIALIZE(amount_commitment)
|
||||
BOOST_END_VERSION_UNDER(1)
|
||||
BOOST_SERIALIZE(opt_proof)
|
||||
BOOST_SERIALIZE(opt_asset_id)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
|
@ -816,6 +816,21 @@ namespace currency
|
|||
};
|
||||
|
||||
|
||||
struct asset_operation_ownership_proof
|
||||
{
|
||||
crypto::generic_schnorr_sig_s gss;
|
||||
uint8_t version = 0;
|
||||
|
||||
BEGIN_VERSIONED_SERIALIZE(0, version)
|
||||
FIELD(gss)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(gss)
|
||||
BOOST_END_VERSION_UNDER(1)
|
||||
BOOST_SERIALIZE(version)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
|
||||
struct extra_padding
|
||||
|
|
@ -921,7 +936,7 @@ namespace currency
|
|||
|
||||
typedef boost::variant<NLSAG_sig, void_sig, ZC_sig, zarcanum_sig> signature_v;
|
||||
|
||||
typedef boost::variant<zc_asset_surjection_proof, zc_outs_range_proof, zc_balance_proof, asset_operation_proof> proof_v;
|
||||
typedef boost::variant<zc_asset_surjection_proof, zc_outs_range_proof, zc_balance_proof, asset_operation_proof, asset_operation_ownership_proof> proof_v;
|
||||
|
||||
|
||||
//include backward compatibility defintions
|
||||
|
|
@ -1108,6 +1123,7 @@ BLOB_SERIALIZER(currency::txout_to_key);
|
|||
|
||||
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);
|
||||
|
||||
|
||||
// txin_v variant currency
|
||||
|
|
@ -1178,6 +1194,7 @@ SET_VARIANT_TAGS(currency::zc_balance_proof, 48, "zc_balance_proof");
|
|||
|
||||
SET_VARIANT_TAGS(currency::asset_descriptor_operation, 49, "asset_descriptor_base");
|
||||
SET_VARIANT_TAGS(currency::asset_operation_proof, 50, "asset_operation_proof");
|
||||
SET_VARIANT_TAGS(currency::asset_operation_ownership_proof, 51, "asset_operation_ownership_proof");
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2019 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#ifndef TESTNET
|
||||
#define CURRENCY_FORMATION_VERSION 84
|
||||
#else
|
||||
#define CURRENCY_FORMATION_VERSION 94
|
||||
#define CURRENCY_FORMATION_VERSION 97
|
||||
#endif
|
||||
|
||||
#define CURRENCY_GENESIS_NONCE (CURRENCY_FORMATION_VERSION + 101011010121) //bender's nightmare
|
||||
|
|
@ -227,7 +227,7 @@
|
|||
#define CURRENCY_POOLDATA_FOLDERNAME_PREFIX "poolstate_"
|
||||
#define CURRENCY_POOLDATA_FOLDERNAME_SUFFIX "_v1"
|
||||
#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_PREFIX "blockchain_"
|
||||
#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX "_v1"
|
||||
#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX "_v2"
|
||||
|
||||
#define P2P_NET_DATA_FILENAME "p2pstate.bin"
|
||||
#define MINER_CONFIG_FILENAME "miner_conf.json"
|
||||
|
|
@ -250,8 +250,8 @@
|
|||
#define BC_OFFERS_CURRENCY_MARKET_FILENAME "market.bin"
|
||||
|
||||
#ifndef TESTNET
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION 161
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION 161
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION 162
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION 162
|
||||
#else
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION (CURRENCY_FORMATION_VERSION+76)
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+76)
|
||||
|
|
@ -264,10 +264,10 @@
|
|||
#define BLOCK_MINOR_VERSION_GENESIS 0
|
||||
#define BLOCK_MAJOR_VERSION_INITIAL 0
|
||||
#ifndef TESTNET
|
||||
#define ZANO_HARDFORK_01_AFTER_HEIGHT 194624
|
||||
#define ZANO_HARDFORK_02_AFTER_HEIGHT 999999
|
||||
#define ZANO_HARDFORK_03_AFTER_HEIGHT 1082577
|
||||
#define ZANO_HARDFORK_04_AFTER_HEIGHT 999999999
|
||||
#define ZANO_HARDFORK_01_AFTER_HEIGHT 194624 // 2019-09-21 20:25:16
|
||||
#define ZANO_HARDFORK_02_AFTER_HEIGHT 999999 // 2021-04-05 09:11:45
|
||||
#define ZANO_HARDFORK_03_AFTER_HEIGHT 1082577 // 2021-06-01 23:28:10
|
||||
#define ZANO_HARDFORK_04_AFTER_HEIGHT 2555000 // 2024-03-21 10:16:46 (expected)
|
||||
#else
|
||||
/////// Zarcanum Testnet //////////////////////////////
|
||||
#define ZANO_HARDFORK_01_AFTER_HEIGHT 0
|
||||
|
|
|
|||
|
|
@ -76,7 +76,10 @@ namespace currency
|
|||
bool core::handle_command_line(const boost::program_options::variables_map& vm)
|
||||
{
|
||||
m_config_folder = command_line::get_arg(vm, command_line::arg_data_dir);
|
||||
m_stop_after_height = static_cast<uint64_t>(command_line::get_arg(vm, command_line::arg_stop_after_height));
|
||||
m_stop_after_height = 0;
|
||||
if(command_line::has_arg(vm, command_line::arg_stop_after_height))
|
||||
m_stop_after_height = static_cast<uint64_t>(command_line::get_arg(vm, command_line::arg_stop_after_height));
|
||||
|
||||
if (m_stop_after_height != 0)
|
||||
{
|
||||
LOG_PRINT_YELLOW("Daemon will STOP after block " << m_stop_after_height, LOG_LEVEL_0);
|
||||
|
|
|
|||
|
|
@ -171,8 +171,8 @@ namespace currency
|
|||
asset_descriptor_operation ado{};
|
||||
if (is_asset_emitting_transaction(tx, &ado))
|
||||
{
|
||||
crypto::point_t asset_id_pt = crypto::c_point_0;
|
||||
calculate_asset_id(ado.descriptor.owner, &asset_id_pt, nullptr); // TODO @#@# optimization: this expensive calculation should be done only once
|
||||
crypto::point_t asset_id_pt{};
|
||||
CHECK_AND_ASSERT_MES(get_or_calculate_asset_id(ado, &asset_id_pt, nullptr), false, "get_or_calculate_asset_id failed"); // TODO @#@# expensive operation, consider caching
|
||||
pseudo_outs_blinded_asset_ids.emplace_back(asset_id_pt); // additional ring member for asset emitting tx
|
||||
}
|
||||
|
||||
|
|
@ -301,8 +301,8 @@ namespace currency
|
|||
#ifndef NDEBUG
|
||||
CHECK_AND_ASSERT_MES(commitment_to_zero == secret_x * crypto::c_point_G, false, "internal error: commitment_to_zero is malformed (G)");
|
||||
#endif
|
||||
r = crypto::generate_schnorr_sig<crypto::gt_G>(tx_id, commitment_to_zero, secret_x, proof.ss);
|
||||
CHECK_AND_ASSERT_MES(r, false, "generate_schnorr_sig (G) failed");
|
||||
r = crypto::generate_double_schnorr_sig<crypto::gt_G, crypto::gt_G>(tx_id, commitment_to_zero, secret_x, ogc.tx_pub_key_p, ogc.tx_key.sec, proof.dss);
|
||||
CHECK_AND_ASSERT_MES(r, false, "generate_double_schnorr_sig (G, G) failed");
|
||||
}
|
||||
else // i.e. zc_inputs_count != 0
|
||||
{
|
||||
|
|
@ -326,8 +326,8 @@ namespace currency
|
|||
bool commitment_to_zero_is_sane = commitment_to_zero == secret_x * crypto::c_point_X;
|
||||
CHECK_AND_ASSERT_MES(commitment_to_zero_is_sane, false, "internal error: commitment_to_zero is malformed (X)");
|
||||
#endif
|
||||
r = crypto::generate_schnorr_sig<crypto::gt_X>(tx_id, commitment_to_zero, secret_x, proof.ss);
|
||||
CHECK_AND_ASSERT_MES(r, false, "generate_schnorr_sig (X) failed");
|
||||
r = crypto::generate_double_schnorr_sig<crypto::gt_X, crypto::gt_G>(tx_id, commitment_to_zero, secret_x, ogc.tx_pub_key_p, ogc.tx_key.sec, proof.dss);
|
||||
CHECK_AND_ASSERT_MES(r, false, "genergenerate_double_schnorr_sigate_schnorr_sig (X, G) failed");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -447,11 +447,9 @@ namespace currency
|
|||
tx = AUTO_VAL_INIT_T(transaction);
|
||||
tx.version = tx_version;
|
||||
|
||||
keypair txkey_local{};
|
||||
if (!tx_one_time_key_to_use)
|
||||
txkey_local = keypair::generate();
|
||||
const keypair& txkey = tx_one_time_key_to_use ? *tx_one_time_key_to_use : txkey_local;
|
||||
add_tx_pub_key_to_extra(tx, txkey.pub);
|
||||
tx_generation_context tx_gen_context{};
|
||||
tx_gen_context.set_tx_key(tx_one_time_key_to_use ? *tx_one_time_key_to_use : keypair::generate());
|
||||
add_tx_pub_key_to_extra(tx, tx_gen_context.tx_key.pub);
|
||||
if (extra_nonce.size())
|
||||
if (!add_tx_extra_userdata(tx, extra_nonce))
|
||||
return false;
|
||||
|
|
@ -488,7 +486,6 @@ namespace currency
|
|||
}
|
||||
|
||||
// fill outputs
|
||||
tx_generation_context tx_gen_context{};
|
||||
tx_gen_context.resize(zc_ins_count, destinations.size()); // auxiliary data for each output
|
||||
uint64_t output_index = 0;
|
||||
std::set<uint16_t> deriv_cache;
|
||||
|
|
@ -496,7 +493,7 @@ namespace currency
|
|||
{
|
||||
finalized_tx result = AUTO_VAL_INIT(result);
|
||||
uint8_t tx_outs_attr = 0;
|
||||
r = construct_tx_out(d, txkey.sec, output_index, tx, deriv_cache, account_keys(),
|
||||
r = construct_tx_out(d, tx_gen_context.tx_key.sec, output_index, tx, deriv_cache, account_keys(),
|
||||
tx_gen_context.asset_id_blinding_masks[output_index], tx_gen_context.amount_blinding_masks[output_index],
|
||||
tx_gen_context.blinded_asset_ids[output_index], tx_gen_context.amount_commitments[output_index], result, tx_outs_attr);
|
||||
CHECK_AND_ASSERT_MES(r, false, "construct_tx_out failed, output #" << output_index << ", amount: " << print_money_brief(d.amount));
|
||||
|
|
@ -576,7 +573,7 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool validate_asset_operation_amount_proof(asset_op_verification_context& context)// const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado, crypto::public_key& asset_id)
|
||||
bool validate_asset_operation_amount_commitment(asset_op_verification_context& context)
|
||||
{
|
||||
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);
|
||||
|
|
@ -608,6 +605,8 @@ namespace currency
|
|||
bool r = get_type_in_variant_container<zc_balance_proof>(tx.proofs, balance_proof);
|
||||
CHECK_AND_ASSERT_MES(r, false, "zc_balance_proof is missing in tx proofs");
|
||||
|
||||
crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx);
|
||||
|
||||
size_t zc_inputs_count = 0;
|
||||
uint64_t bare_inputs_sum = additional_inputs_amount_and_fees_for_mining_tx;
|
||||
for(auto& vin : tx.vin)
|
||||
|
|
@ -645,7 +644,7 @@ namespace currency
|
|||
{
|
||||
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT)
|
||||
{
|
||||
// opt_amount_commitment supposed to be validated earlier in validate_asset_operation()
|
||||
// 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
|
||||
}
|
||||
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
|
||||
|
|
@ -675,13 +674,13 @@ namespace currency
|
|||
CHECK_AND_ASSERT_MES(zc_inputs_count == zc_sigs_count, false, "zc inputs count (" << zc_inputs_count << ") and zc sigs count (" << zc_sigs_count << ") missmatch");
|
||||
if (zc_inputs_count > 0)
|
||||
{
|
||||
r = crypto::verify_schnorr_sig<crypto::gt_X>(tx_id, commitment_to_zero.to_public_key(), balance_proof.ss);
|
||||
CHECK_AND_ASSERT_MES(r, false, "zc_balance_proof (X) is invalid");
|
||||
r = crypto::verify_double_schnorr_sig<crypto::gt_X, crypto::gt_G>(tx_id, commitment_to_zero, tx_pub_key, balance_proof.dss);
|
||||
CHECK_AND_ASSERT_MES(r, false, "verify_double_schnorr_sig (X, G) is invalid");
|
||||
}
|
||||
else
|
||||
{
|
||||
r = crypto::verify_schnorr_sig<crypto::gt_G>(tx_id, commitment_to_zero.to_public_key(), balance_proof.ss);
|
||||
CHECK_AND_ASSERT_MES(r, false, "zc_balance_proof (G) is invalid");
|
||||
r = crypto::verify_double_schnorr_sig<crypto::gt_G, crypto::gt_G>(tx_id, commitment_to_zero, tx_pub_key, balance_proof.dss);
|
||||
CHECK_AND_ASSERT_MES(r, false, "verify_double_schnorr_sig (G, G) is invalid");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1138,20 +1137,21 @@ namespace currency
|
|||
return origin_blob;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool validate_ado_update_allowed(const asset_descriptor_base& a, const asset_descriptor_base& b)
|
||||
bool validate_ado_update_allowed(const asset_descriptor_base& new_ado, const asset_descriptor_base& prev_ado)
|
||||
{
|
||||
if (a.total_max_supply != b.total_max_supply) return false;
|
||||
//if (a.current_supply != b.current_supply) return false;
|
||||
if (a.decimal_point != b.decimal_point) return false;
|
||||
if (a.ticker != b.ticker) return false;
|
||||
if (a.full_name != b.full_name) return false;
|
||||
if (new_ado.total_max_supply != prev_ado.total_max_supply) return false;
|
||||
if (new_ado.current_supply > prev_ado.total_max_supply) return false;
|
||||
if (new_ado.decimal_point != prev_ado.decimal_point) return false;
|
||||
if (new_ado.ticker != prev_ado.ticker) return false;
|
||||
if (new_ado.full_name != prev_ado.full_name) return false;
|
||||
//a.meta_info;
|
||||
if (a.owner != b.owner) return false;
|
||||
if (a.hidden_supply != b.hidden_supply) return false;
|
||||
//if (a.owner != b.owner) return false;
|
||||
if (new_ado.hidden_supply != prev_ado.hidden_supply) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
/*
|
||||
crypto::hash get_signature_hash_for_asset_operation(const asset_descriptor_operation& ado)
|
||||
{
|
||||
asset_descriptor_operation ado_local = ado;
|
||||
|
|
@ -1165,6 +1165,7 @@ namespace currency
|
|||
{
|
||||
op.opt_proof = boost::none;
|
||||
}
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------
|
||||
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, uint8_t tx_outs_attr /* = CURRENCY_TO_KEY_OUT_RELAXED */)
|
||||
|
|
@ -2111,20 +2112,45 @@ namespace currency
|
|||
}
|
||||
|
||||
#define CRYPTO_HASH_ASSET_ID_ITERATIONS 1024
|
||||
void calculate_asset_id(const crypto::public_key& asset_owner, crypto::point_t* p_result_point, crypto::public_key* p_result_pub_key)
|
||||
bool get_or_calculate_asset_id(const asset_descriptor_operation& ado, crypto::point_t* p_result_point, crypto::public_key* p_result_pub_key)
|
||||
{
|
||||
crypto::hash h = get_hash_from_POD_objects(CRYPTO_HDS_ASSET_ID, asset_owner);
|
||||
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT ||
|
||||
ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE ||
|
||||
ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN )
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(ado.opt_asset_id.has_value(), false, "ado.opt_asset_id has no value, op: " << (int)ado.operation_type << ", " << get_asset_operation_type_string(ado.operation_type));
|
||||
//LOG_PRINT_YELLOW("ado.opt_asset_id = " << ado.opt_asset_id.get(), LOG_LEVEL_0);
|
||||
if (p_result_pub_key)
|
||||
*p_result_pub_key = ado.opt_asset_id.get();
|
||||
if (p_result_point)
|
||||
*p_result_point = crypto::point_t(ado.opt_asset_id.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
// otherwise, 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);
|
||||
crypto::hash h = hsc.calc_hash_no_reduce();
|
||||
|
||||
// this hash function needs to be computationally expensive (s.a. the whitepaper)
|
||||
for(uint64_t i = 0; i < CRYPTO_HASH_ASSET_ID_ITERATIONS; ++i)
|
||||
h = get_hash_from_POD_objects(CRYPTO_HDS_ASSET_ID, h, i);
|
||||
|
||||
crypto::point_t local_point{};
|
||||
if (!p_result_point)
|
||||
p_result_point = &local_point;
|
||||
*p_result_point = crypto::hash_helper_t::hp(&h, sizeof h);
|
||||
crypto::point_t result = crypto::hash_helper_t::hp(&h, sizeof h);
|
||||
if (p_result_point)
|
||||
*p_result_point = result;
|
||||
if (p_result_pub_key)
|
||||
p_result_point->to_public_key(*p_result_pub_key);
|
||||
result.to_public_key(*p_result_pub_key);
|
||||
|
||||
//LOG_PRINT_YELLOW("calculated asset_id = " << result, LOG_LEVEL_0);
|
||||
return true;
|
||||
}
|
||||
|
||||
const asset_descriptor_base& get_native_coin_asset_descriptor()
|
||||
|
|
@ -2155,14 +2181,20 @@ 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");
|
||||
//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
|
||||
|
||||
ado.descriptor.owner = sender_account_keys.account_address.spend_public_key;
|
||||
|
||||
calculate_asset_id(ado.descriptor.owner, &gen_context.ao_asset_id_pt, &gen_context.ao_asset_id);
|
||||
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");
|
||||
|
||||
// calculate amount blinding mask
|
||||
gen_context.ao_amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_ASSET_CONTROL_ABM, asset_control_key, tx_key.pub);
|
||||
gen_context.ao_amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_ASSET_CONTROL_ABM, tx_key.sec);
|
||||
|
||||
// set correct asset_id to the corresponding destination entries
|
||||
uint64_t amount_of_emitted_asset = 0;
|
||||
|
|
@ -2179,16 +2211,47 @@ namespace currency
|
|||
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();
|
||||
}
|
||||
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
|
||||
{
|
||||
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");
|
||||
|
||||
// calculate amount blinding mask
|
||||
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
|
||||
uint64_t amount_of_burned_assets = 0;
|
||||
for (auto& item : ftp.sources)
|
||||
{
|
||||
if (item.asset_id == gen_context.ao_asset_id)
|
||||
{
|
||||
amount_of_burned_assets += item.amount;
|
||||
}
|
||||
}
|
||||
for (auto& item : ftp.prepared_destinations)
|
||||
{
|
||||
if (item.asset_id == gen_context.ao_asset_id)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(amount_of_burned_assets >= item.amount, "Failed to find burn amount, failed condition: amount_of_burned_assets(" << amount_of_burned_assets << ") >= item.amount(" << item.amount << ")");
|
||||
amount_of_burned_assets -= item.amount;
|
||||
}
|
||||
}
|
||||
ado.descriptor.current_supply -= amount_of_burned_assets;
|
||||
|
||||
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();
|
||||
|
||||
if (ftp.pevents_dispatcher) ftp.pevents_dispatcher->RAISE_DEBUG_EVENT(wde_construct_tx_handle_asset_descriptor_operation_before_burn{ &ado });
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(ado.opt_asset_id, false, "ado.opt_asset_id is not found at ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT");
|
||||
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");
|
||||
|
||||
gen_context.ao_asset_id = *ado.opt_asset_id;
|
||||
gen_context.ao_asset_id_pt.from_public_key(gen_context.ao_asset_id);
|
||||
// calculate amount blinding mask
|
||||
gen_context.ao_amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_ASSET_CONTROL_ABM, ftp.asset_control_key, tx_key.pub);
|
||||
gen_context.ao_amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_ASSET_CONTROL_ABM, tx_key.sec);
|
||||
|
||||
// set correct asset_id to the corresponding destination entries
|
||||
uint64_t amount_of_emitted_asset = 0;
|
||||
|
|
@ -2213,47 +2276,27 @@ namespace currency
|
|||
|
||||
//fields that not supposed to be changed?
|
||||
}
|
||||
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(ado.opt_asset_id, false, "ado.opt_asset_id is not found at ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN");
|
||||
|
||||
gen_context.ao_asset_id = *ado.opt_asset_id;
|
||||
gen_context.ao_asset_id_pt.from_public_key(gen_context.ao_asset_id);
|
||||
// calculate amount blinding mask
|
||||
gen_context.ao_amount_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_ASSET_CONTROL_ABM, ftp.asset_control_key, tx_key.pub);
|
||||
gen_context.ao_commitment_in_outputs = true;
|
||||
|
||||
// set correct asset_id to the corresponding destination entries
|
||||
uint64_t amount_of_burned_assets = 0;
|
||||
for (auto& item: ftp.sources)
|
||||
{
|
||||
if (item.asset_id == gen_context.ao_asset_id)
|
||||
{
|
||||
amount_of_burned_assets += item.amount;
|
||||
}
|
||||
}
|
||||
for (auto& item : ftp.prepared_destinations)
|
||||
{
|
||||
if (item.asset_id == gen_context.ao_asset_id )
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(amount_of_burned_assets >= item.amount, "Failed to find burn amount, failed condition: amount_of_burned_assets(" << amount_of_burned_assets << ") >= item.amount("<< item.amount << ")");
|
||||
amount_of_burned_assets -= item.amount;
|
||||
}
|
||||
}
|
||||
ado.descriptor.current_supply -= amount_of_burned_assets;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
if (ftp.pevents_dispatcher) ftp.pevents_dispatcher->RAISE_DEBUG_EVENT(wde_construct_tx_handle_asset_descriptor_operation_before_seal{ &ado });
|
||||
|
||||
ftp.need_to_generate_ado_proof = true;
|
||||
/*
|
||||
//seal it with owners signature
|
||||
crypto::signature sig = currency::null_sig;
|
||||
crypto::public_key pub_k = currency::null_pkey;
|
||||
crypto::secret_key_to_public_key(ftp.asset_control_key, pub_k);
|
||||
crypto::generate_signature(get_signature_hash_for_asset_operation(ado), pub_k, ftp.asset_control_key, sig);
|
||||
crypto::hash h = get_signature_hash_for_asset_operation(ado);
|
||||
if (ftp.pthirdparty_sign_handler)
|
||||
{
|
||||
bool r = ftp.pthirdparty_sign_handler->sign(h, ftp.ado_current_asset_owner, sig);
|
||||
CHECK_AND_ASSERT_MES(r, false, "asset thirparty sign failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
crypto::public_key pub_k = currency::null_pkey;
|
||||
crypto::secret_key_to_public_key(sender_account_keys.spend_secret_key, pub_k);
|
||||
CHECK_AND_ASSERT_MES(ftp.ado_current_asset_owner == pub_k, false, "asset owner key not matched with provided private key for asset operation signing");
|
||||
crypto::generate_signature(h, pub_k, account_keys.spend_secret_key, sig);
|
||||
}
|
||||
ado.opt_proof = sig;
|
||||
*/
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2438,15 +2481,14 @@ namespace currency
|
|||
LOG_PRINT_YELLOW("WARNING: tx v1 should not use ZC inputs", LOG_LEVEL_0);
|
||||
}
|
||||
|
||||
tx_generation_context& gen_context = result.ftp.gen_context;
|
||||
|
||||
|
||||
keypair txkey = AUTO_VAL_INIT(txkey);
|
||||
if (!append_mode)
|
||||
{
|
||||
txkey = keypair::generate();
|
||||
gen_context.set_tx_key(keypair::generate());
|
||||
//deterministic_generate_tx_onetime_key(key_images_total, sender_account_keys, txkey);
|
||||
add_tx_pub_key_to_extra(tx, txkey.pub);
|
||||
one_time_tx_secret_key = txkey.sec;
|
||||
add_tx_pub_key_to_extra(tx, gen_context.tx_key.pub);
|
||||
one_time_tx_secret_key = gen_context.tx_key.sec;
|
||||
|
||||
//add flags
|
||||
etc_tx_flags16_t e = AUTO_VAL_INIT(e);
|
||||
|
|
@ -2455,13 +2497,12 @@ namespace currency
|
|||
|
||||
//include offers if need
|
||||
tx.attachment = attachments;
|
||||
encrypt_attachments(tx, sender_account_keys, crypt_destination_addr, txkey, result.derivation);
|
||||
encrypt_attachments(tx, sender_account_keys, crypt_destination_addr, gen_context.tx_key, result.derivation);
|
||||
}
|
||||
else
|
||||
{
|
||||
txkey.pub = get_tx_pub_key_from_extra(tx);
|
||||
txkey.sec = one_time_tx_secret_key;
|
||||
CHECK_AND_ASSERT_MES(txkey.pub != null_pkey && txkey.sec != null_skey, false, "In append mode both public and secret keys must be provided");
|
||||
gen_context.set_tx_key(keypair{get_tx_pub_key_from_extra(tx), one_time_tx_secret_key});
|
||||
CHECK_AND_ASSERT_MES(gen_context.tx_key.pub != null_pkey && gen_context.tx_key.sec != null_skey, false, "In append mode both public and secret keys must be provided");
|
||||
|
||||
//separately encrypt attachments without putting extra
|
||||
result.derivation = get_encryption_key_derivation(true, tx, sender_account_keys);
|
||||
|
|
@ -2471,7 +2512,7 @@ namespace currency
|
|||
std::vector<extra_v> extra_local = extra;
|
||||
std::vector<attachment_v> attachments_local = attachments;
|
||||
|
||||
encrypt_attach_visitor v(was_attachment_crypted_entries, derivation, txkey, account_public_address(), sender_account_keys);
|
||||
encrypt_attach_visitor v(was_attachment_crypted_entries, derivation, gen_context.tx_key, account_public_address(), sender_account_keys);
|
||||
for (auto& a : attachments_local)
|
||||
boost::apply_visitor(v, a);
|
||||
for (auto& a : extra_local)
|
||||
|
|
@ -2481,7 +2522,7 @@ namespace currency
|
|||
tx.attachment.insert(tx.attachment.end(), attachments_local.begin(), attachments_local.end());
|
||||
tx.extra.insert(tx.extra.end(), extra_local.begin(), extra_local.end());
|
||||
|
||||
for (const auto in : tx.vin)
|
||||
for (const auto& in : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_zc_input))
|
||||
{
|
||||
|
|
@ -2499,8 +2540,6 @@ namespace currency
|
|||
// OUTs
|
||||
//
|
||||
std::vector<tx_destination_entry> shuffled_dsts(destinations);
|
||||
//size_t outputs_to_be_constructed = shuffled_dsts.size();
|
||||
tx_generation_context& gen_context = result.ftp.gen_context;
|
||||
gen_context.resize(zc_inputs_count, tx.vout.size() + shuffled_dsts.size());
|
||||
|
||||
// ASSET oprations handling
|
||||
|
|
@ -2510,7 +2549,7 @@ namespace currency
|
|||
pado = get_type_in_variant_container<asset_descriptor_operation>(tx.extra);
|
||||
if (pado)
|
||||
{
|
||||
bool r = construct_tx_handle_ado(sender_account_keys, ftp, *pado, gen_context, txkey, shuffled_dsts);
|
||||
bool r = construct_tx_handle_ado(sender_account_keys, ftp, *pado, gen_context, gen_context.tx_key, shuffled_dsts);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construct_tx_handle_ado()");
|
||||
if (ftp.pevents_dispatcher) ftp.pevents_dispatcher->RAISE_DEBUG_EVENT(wde_construct_tx_handle_asset_descriptor_operation{ pado });
|
||||
}
|
||||
|
|
@ -2533,7 +2572,7 @@ namespace currency
|
|||
if (!(flags & TX_FLAG_SIGNATURE_MODE_SEPARATE) && all_inputs_are_obviously_native_coins && gen_context.ao_asset_id == currency::null_pkey)
|
||||
dst_entr.flags |= tx_destination_entry_flags::tdef_explicit_native_asset_id; // all inputs are obviously native coins -- all outputs must have explicit asset ids (unless there's an asset emission)
|
||||
|
||||
r = construct_tx_out(dst_entr, txkey.sec, output_index, tx, deriv_cache, sender_account_keys,
|
||||
r = construct_tx_out(dst_entr, gen_context.tx_key.sec, output_index, tx, deriv_cache, sender_account_keys,
|
||||
gen_context.asset_id_blinding_masks[output_index], gen_context.amount_blinding_masks[output_index],
|
||||
gen_context.blinded_asset_ids[output_index], gen_context.amount_commitments[output_index], result, tx_outs_attr);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construct tx out");
|
||||
|
|
@ -2642,7 +2681,7 @@ namespace currency
|
|||
else
|
||||
{
|
||||
// NLSAG
|
||||
r = generate_NLSAG_sig(tx_hash_for_signature, tx_prefix_hash, i_ + input_starter_index, source_entry, sender_account_keys, in_contexts[i_mapped], txkey, flags, tx, &ss_ring_s);
|
||||
r = generate_NLSAG_sig(tx_hash_for_signature, tx_prefix_hash, i_ + input_starter_index, source_entry, sender_account_keys, in_contexts[i_mapped], gen_context.tx_key, flags, tx, &ss_ring_s);
|
||||
CHECK_AND_ASSERT_MES(r, false, "generate_NLSAG_sig failed");
|
||||
}
|
||||
|
||||
|
|
@ -2684,6 +2723,25 @@ namespace currency
|
|||
aop.opt_amount_commitment_g_proof = aop_g_sig;
|
||||
tx.proofs.emplace_back(std::move(aop));
|
||||
}
|
||||
if(ftp.need_to_generate_ado_proof)
|
||||
{
|
||||
asset_operation_ownership_proof aoop = AUTO_VAL_INIT(aoop);
|
||||
|
||||
if (ftp.pthirdparty_sign_handler)
|
||||
{
|
||||
//ask third party to generate proof
|
||||
r = ftp.pthirdparty_sign_handler->sign(tx_prefix_hash, ftp.ado_current_asset_owner, aoop.gss);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to sign ado by thirdparty");
|
||||
}
|
||||
else
|
||||
{
|
||||
//generate signature by wallet account
|
||||
r = crypto::generate_schnorr_sig(tx_prefix_hash, ftp.ado_current_asset_owner, sender_account_keys.spend_secret_key, aoop.gss);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to sign ado proof");
|
||||
}
|
||||
if (ftp.pevents_dispatcher) ftp.pevents_dispatcher->RAISE_DEBUG_EVENT(wde_construct_tx_after_asset_ownership_proof_generated{ &aoop });
|
||||
tx.proofs.emplace_back(aoop);
|
||||
}
|
||||
}
|
||||
|
||||
//size_t prefix_size = get_object_blobsize(static_cast<const transaction_prefix&>(tx));
|
||||
|
|
@ -3180,7 +3238,7 @@ namespace currency
|
|||
if (P_prime.to_public_key() != zo.stealth_address)
|
||||
return false;
|
||||
|
||||
crypto::point_t Q_prime = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_CONCEALING_POINT, h) * 8 * crypto::point_t(addr.view_public_key); // Q' * 8 =? Hs(domain_sep, Hs(8 * r * V, i) ) * 8 * V
|
||||
crypto::point_t Q_prime = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_CONCEALING_POINT, h) * crypto::point_t(addr.view_public_key).modify_mul8(); // Q' * 8 =? Hs(domain_sep, Hs(8 * r * V, i) ) * 8 * V
|
||||
if (Q_prime != crypto::point_t(zo.concealing_point).modify_mul8())
|
||||
return false;
|
||||
|
||||
|
|
@ -3319,7 +3377,7 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool set_payment_id_to_tx(std::vector<attachment_v>& att, const std::string& payment_id)
|
||||
bool set_payment_id_to_tx(std::vector<attachment_v>& att, const std::string& payment_id, bool is_in_hardfork4)
|
||||
{
|
||||
if (!is_payment_id_size_ok(payment_id))
|
||||
return false;
|
||||
|
|
@ -3327,6 +3385,10 @@ namespace currency
|
|||
tx_service_attachment tsa = AUTO_VAL_INIT(tsa);
|
||||
tsa.service_id = BC_PAYMENT_ID_SERVICE_ID;
|
||||
tsa.body = payment_id;
|
||||
if (is_in_hardfork4)
|
||||
{
|
||||
tsa.flags = TX_SERVICE_ATTACHMENT_ENCRYPT_BODY;
|
||||
}
|
||||
att.push_back(tsa);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,15 +134,18 @@ namespace currency
|
|||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct htlc_info
|
||||
{
|
||||
bool hltc_our_out_is_before_expiration;
|
||||
};
|
||||
struct htlc_info
|
||||
{
|
||||
bool hltc_our_out_is_before_expiration;
|
||||
};
|
||||
|
||||
struct thirdparty_sign_handler
|
||||
{
|
||||
virtual bool sign(const crypto::hash& h, const crypto::public_key& owner_public_key, crypto::generic_schnorr_sig& sig);
|
||||
};
|
||||
|
||||
struct finalize_tx_param
|
||||
{
|
||||
|
||||
uint64_t unlock_time;
|
||||
std::vector<currency::extra_v> extra;
|
||||
std::vector<currency::attachment_v> attachments;
|
||||
|
|
@ -158,10 +161,15 @@ namespace currency
|
|||
crypto::public_key spend_pub_key; // only for validations
|
||||
uint64_t tx_version;
|
||||
uint64_t mode_separate_fee = 0;
|
||||
crypto::secret_key asset_control_key = currency::null_skey;
|
||||
|
||||
epee::misc_utils::events_dispatcher* pevents_dispatcher;
|
||||
|
||||
tx_generation_context gen_context{}; // solely for consolidated txs
|
||||
|
||||
//crypto::secret_key asset_control_key = currency::null_skey;
|
||||
crypto::public_key ado_current_asset_owner = null_pkey;
|
||||
thirdparty_sign_handler* pthirdparty_sign_handler = nullptr;
|
||||
mutable bool need_to_generate_ado_proof = false;
|
||||
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(unlock_time)
|
||||
|
|
@ -179,9 +187,12 @@ namespace currency
|
|||
FIELD(spend_pub_key)
|
||||
FIELD(tx_version)
|
||||
FIELD(mode_separate_fee)
|
||||
FIELD(asset_control_key)
|
||||
if (flags & TX_FLAG_SIGNATURE_MODE_SEPARATE)
|
||||
{
|
||||
FIELD(gen_context);
|
||||
}
|
||||
FIELD(ado_current_asset_owner)
|
||||
FIELD(need_to_generate_ado_proof)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
|
|
@ -264,7 +275,7 @@ namespace currency
|
|||
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);
|
||||
bool validate_asset_operation_amount_proof(asset_op_verification_context& context);
|
||||
bool validate_asset_operation_amount_commitment(asset_op_verification_context& context);
|
||||
const char* get_asset_operation_type_string(size_t asset_operation_type, bool short_name = false);
|
||||
//---------------------------------------------------------------
|
||||
bool construct_miner_tx(size_t height, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins,
|
||||
|
|
@ -331,7 +342,7 @@ namespace currency
|
|||
|
||||
uint64_t get_tx_version(uint64_t tx_expected_block_height, const hard_forks_descriptor& hfd); // returns tx version based on the height of the block where the transaction is expected to be
|
||||
bool construct_tx(const account_keys& sender_account_keys, const finalize_tx_param& param, finalized_tx& result);
|
||||
void calculate_asset_id(const crypto::public_key& asset_owner, crypto::point_t* p_result_point, crypto::public_key* p_result_pub_key);
|
||||
bool get_or_calculate_asset_id(const asset_descriptor_operation& ado, crypto::point_t* p_result_point, crypto::public_key* p_result_pub_key);
|
||||
const asset_descriptor_base& get_native_coin_asset_descriptor();
|
||||
|
||||
bool sign_multisig_input_in_tx(currency::transaction& tx, size_t ms_input_index, const currency::account_keys& keys, const currency::transaction& source_tx, bool *p_is_input_fully_signed = nullptr);
|
||||
|
|
@ -420,7 +431,7 @@ namespace currency
|
|||
|
||||
bool addendum_to_hexstr(const std::vector<crypto::hash>& add, std::string& hex_buff);
|
||||
bool hexstr_to_addendum(const std::string& hex_buff, std::vector<crypto::hash>& add);
|
||||
bool set_payment_id_to_tx(std::vector<attachment_v>& att, const std::string& payment_id);
|
||||
bool set_payment_id_to_tx(std::vector<attachment_v>& att, const std::string& payment_id, bool is_in_hardfork4 = false);
|
||||
bool add_padding_to_tx(transaction& tx, size_t count);
|
||||
bool is_service_tx(const transaction& tx);
|
||||
bool does_tx_have_only_mixin_inputs(const transaction& tx);
|
||||
|
|
@ -661,7 +672,7 @@ namespace currency
|
|||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename t_container>
|
||||
bool get_payment_id_from_tx(const t_container& att, std::string& payment_id)
|
||||
bool get_payment_id_from_decrypted_container(const t_container& att, std::string& payment_id)
|
||||
{
|
||||
tx_service_attachment sa = AUTO_VAL_INIT(sa);
|
||||
if (bc_services::get_first_service_attachment_by_id(att, BC_PAYMENT_ID_SERVICE_ID, "", sa))
|
||||
|
|
|
|||
|
|
@ -398,7 +398,7 @@ namespace currency
|
|||
CATCH_ENTRY2(std::vector<tx_source_entry::output_entry>{});
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool validate_tx_output_details_againt_tx_generation_context(const transaction& tx, const tx_generation_context& gen_context, const crypto::secret_key& onet_time_key)
|
||||
bool validate_tx_output_details_againt_tx_generation_context(const transaction& tx, const tx_generation_context& gen_context)
|
||||
{
|
||||
//TODO: Implement this function before mainnet
|
||||
#ifdef TESTNET
|
||||
|
|
|
|||
|
|
@ -243,6 +243,12 @@ namespace currency
|
|||
amount_blinding_masks.size() == outs_count;
|
||||
}
|
||||
|
||||
void set_tx_key(const keypair& kp)
|
||||
{
|
||||
tx_key = kp;
|
||||
tx_pub_key_p = crypto::point_t(tx_key.pub);
|
||||
}
|
||||
|
||||
// per output data
|
||||
std::vector<crypto::point_t> asset_ids;
|
||||
std::vector<crypto::point_t> blinded_asset_ids; // generate_zc_outs_range_proof
|
||||
|
|
@ -274,6 +280,10 @@ namespace currency
|
|||
crypto::scalar_t ao_amount_blinding_mask {}; // generate_tx_balance_proof generate_ZC_sig
|
||||
bool ao_commitment_in_outputs = false;
|
||||
|
||||
// per tx data
|
||||
keypair tx_key {}; //
|
||||
crypto::point_t tx_pub_key_p = crypto::c_point_0; // == tx_key.pub
|
||||
|
||||
// consider redesign, some data may possibly be excluded from kv serialization -- sowle
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(asset_ids)
|
||||
|
|
@ -297,6 +307,8 @@ namespace currency
|
|||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_amount_commitment)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_amount_blinding_mask)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(ao_commitment_in_outputs)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(tx_key)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(tx_pub_key_p)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
// solely for consolidated txs, asset opration fields are not serialized
|
||||
|
|
@ -325,10 +337,14 @@ namespace currency
|
|||
//ao_amount_commitment
|
||||
//ao_amount_blinding_mask
|
||||
//ao_commitment_in_outputs
|
||||
|
||||
FIELD(tx_key.pub) // TODO: change to sane serialization FIELD(tx_key)
|
||||
FIELD(tx_key.sec)
|
||||
FIELD(tx_pub_key_p)
|
||||
END_SERIALIZE()
|
||||
}; // struct tx_generation_context
|
||||
|
||||
bool validate_tx_output_details_againt_tx_generation_context(const transaction& tx, const tx_generation_context& gen_context, const crypto::secret_key& onet_time_key);
|
||||
bool validate_tx_output_details_againt_tx_generation_context(const transaction& tx, const tx_generation_context& gen_context);
|
||||
std::string transform_tx_to_str(const transaction& tx);
|
||||
transaction transform_str_to_tx(const std::string& tx_str);
|
||||
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_no_predownload);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_force_predownload);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_process_predownload_from_path);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_validate_predownload);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_predownload_link);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_disable_ntp);
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 18cb69f348bae38186f3a8da8bc9fc9991d38cd1
|
||||
Subproject commit f040b10090a0246ee5f68a37bb4fcc13e6abebcc
|
||||
|
|
@ -118,10 +118,9 @@ namespace currency
|
|||
res.minimum_fee = m_core.get_blockchain_storage().get_core_runtime_config().tx_pool_min_fee;
|
||||
|
||||
auto & hf = m_core.get_blockchain_storage().get_core_runtime_config().hard_forks.m_height_the_hardfork_n_active_after;
|
||||
res.is_hardfok_active.resize(hf.size());
|
||||
for (size_t i = 0; i != hf.size(); i++)
|
||||
{
|
||||
res.is_hardfok_active[i] = m_core.get_blockchain_storage().is_hardfork_active(i);
|
||||
res.is_hardfok_active.push_back(m_core.get_blockchain_storage().is_hardfork_active(i));
|
||||
}
|
||||
|
||||
//conditional values
|
||||
|
|
@ -680,7 +679,7 @@ namespace currency
|
|||
{
|
||||
std::list<currency::extra_alias_entry> al_list;
|
||||
m_core.get_tx_pool().get_aliases_from_tx_pool(al_list);
|
||||
for (const auto a : al_list)
|
||||
for (const auto& a : al_list)
|
||||
{
|
||||
res.aliases_que.push_back(alias_info_to_rpc_alias_info(a));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -793,7 +793,7 @@ namespace currency
|
|||
uint64_t minimum_fee;
|
||||
uint64_t last_block_timestamp;
|
||||
std::string last_block_hash;
|
||||
std::vector<bool> is_hardfok_active;
|
||||
std::list<bool> is_hardfok_active;
|
||||
//market
|
||||
uint64_t offers_count;
|
||||
|
||||
|
|
|
|||
|
|
@ -1681,7 +1681,7 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
|
|||
|
||||
|
||||
std::vector<currency::attachment_v> attachments;
|
||||
if (!payment_id.empty() && !set_payment_id_to_tx(attachments, payment_id))
|
||||
if (!payment_id.empty() && !set_payment_id_to_tx(attachments, payment_id, m_wallet->is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM)))
|
||||
{
|
||||
fail_msg_writer() << "provided (or embedded) payment id can't be set: \"" << payment_id << "\"";
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@
|
|||
#define PROJECT_REVISION "0"
|
||||
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
|
||||
|
||||
#define PROJECT_VERSION_BUILD_NO 253
|
||||
#define PROJECT_VERSION_BUILD_NO 265
|
||||
#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 "]"
|
||||
|
|
|
|||
|
|
@ -400,30 +400,18 @@ void wallet2::process_ado_in_new_transaction(const currency::asset_descriptor_op
|
|||
{
|
||||
do
|
||||
{
|
||||
crypto::public_key asset_id{};
|
||||
if (ado.operation_type != ASSET_DESCRIPTOR_OPERATION_UNDEFINED)
|
||||
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(get_or_calculate_asset_id(ado, nullptr, &asset_id), "get_or_calculate_asset_id failed");
|
||||
|
||||
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
|
||||
{
|
||||
crypto::public_key self_check = AUTO_VAL_INIT(self_check);
|
||||
crypto::secret_key asset_control_key = AUTO_VAL_INIT(asset_control_key);
|
||||
bool r = derive_key_pair_from_key_pair(ptc.tx_pub_key, m_account.get_keys().spend_secret_key, asset_control_key, self_check, CRYPTO_HDS_ASSET_CONTROL_KEY);
|
||||
if (!r)
|
||||
{
|
||||
//not critical error, continue to work
|
||||
LOG_ERROR("Failed to derive_key_pair_from_key_pair for asset_descriptor_operation in tx " << ptc.tx_hash());
|
||||
if (ado.descriptor.owner != m_account.get_public_address().spend_public_key)
|
||||
break;
|
||||
}
|
||||
|
||||
if (self_check != ado.descriptor.owner)
|
||||
{
|
||||
//still not critical error
|
||||
LOG_ERROR("Public key from asset_descriptor_operation(" << ado.descriptor.owner << ") not much with derived public key(" << self_check << "), for tx" << ptc.tx_hash());
|
||||
break;
|
||||
}
|
||||
crypto::public_key asset_id{};
|
||||
calculate_asset_id(ado.descriptor.owner, nullptr, &asset_id);
|
||||
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(m_own_asset_descriptors.count(asset_id) == 0, "asset with asset_id " << asset_id << " has already been registered in the wallet as own asset");
|
||||
wallet_own_asset_context& asset_context = m_own_asset_descriptors[asset_id];
|
||||
asset_context.asset_descriptor = ado.descriptor;
|
||||
asset_context.control_key = asset_control_key;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "New Asset Registered:"
|
||||
|
|
@ -440,22 +428,78 @@ void wallet2::process_ado_in_new_transaction(const currency::asset_descriptor_op
|
|||
if (m_wcallback)
|
||||
m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str());
|
||||
}
|
||||
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
|
||||
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN)
|
||||
{
|
||||
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(ado.opt_asset_id, get_asset_operation_type_string(ado.operation_type) << " failed with empty opt_asset_id");
|
||||
auto it = m_own_asset_descriptors.find(*ado.opt_asset_id);
|
||||
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(it != m_own_asset_descriptors.end(), "asset with asset_id " << *ado.opt_asset_id << " not found during " << get_asset_operation_type_string(ado.operation_type));
|
||||
if (it->second.asset_descriptor.owner != ado.descriptor.owner)
|
||||
auto it = m_own_asset_descriptors.find(asset_id);
|
||||
if (it == m_own_asset_descriptors.end())
|
||||
break;
|
||||
//asset had been updated
|
||||
add_rollback_event(ptc.height, asset_update_event{ it->first, it->second });
|
||||
it->second.asset_descriptor = ado.descriptor;
|
||||
}
|
||||
else if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE )
|
||||
{
|
||||
auto it = m_own_asset_descriptors.find(asset_id);
|
||||
if (it == m_own_asset_descriptors.end())
|
||||
{
|
||||
//ownership of the asset had been transfered
|
||||
add_rollback_event(ptc.height, asset_unown_event{ it->first, it->second });
|
||||
m_own_asset_descriptors.erase(it);
|
||||
if (ado.descriptor.owner == m_account.get_public_address().spend_public_key)
|
||||
{
|
||||
// ownership of the asset acquired
|
||||
|
||||
wallet_own_asset_context& asset_context = m_own_asset_descriptors[asset_id];
|
||||
asset_context.asset_descriptor = ado.descriptor;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Asset ownership acquired:"
|
||||
<< ENDL << "asset id: " << asset_id
|
||||
<< ENDL << "Name: " << ado.descriptor.full_name
|
||||
<< ENDL << "Ticker: " << ado.descriptor.ticker
|
||||
<< ENDL << "Total Max Supply: " << print_asset_money(ado.descriptor.total_max_supply, ado.descriptor.decimal_point)
|
||||
<< ENDL << "Current Supply: " << print_asset_money(ado.descriptor.current_supply, ado.descriptor.decimal_point)
|
||||
<< ENDL << "Decimal Point: " << ado.descriptor.decimal_point;
|
||||
|
||||
|
||||
add_rollback_event(ptc.height, asset_register_event{ asset_id });
|
||||
WLT_LOG_MAGENTA(ss.str(), LOG_LEVEL_0);
|
||||
if (m_wcallback)
|
||||
m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// update event of the asset that we not control, skip
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//asset had been updated
|
||||
add_rollback_event(ptc.height, asset_update_event{ it->first, it->second });
|
||||
it->second.asset_descriptor = ado.descriptor;
|
||||
//update event for asset that we control, check if ownership is still ours
|
||||
if (ado.descriptor.owner != m_account.get_public_address().spend_public_key && !it->second.thirdparty_custody)
|
||||
{
|
||||
//ownership of the asset had been transfered
|
||||
add_rollback_event(ptc.height, asset_unown_event{ it->first, it->second });
|
||||
m_own_asset_descriptors.erase(it);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Asset ownership lost:"
|
||||
<< ENDL << "asset id: " << asset_id
|
||||
<< ENDL << "New owner: " << ado.descriptor.owner
|
||||
<< ENDL << "Name: " << ado.descriptor.full_name
|
||||
<< ENDL << "Ticker: " << ado.descriptor.ticker
|
||||
<< ENDL << "Total Max Supply: " << print_asset_money(ado.descriptor.total_max_supply, ado.descriptor.decimal_point)
|
||||
<< ENDL << "Current Supply: " << print_asset_money(ado.descriptor.current_supply, ado.descriptor.decimal_point)
|
||||
<< ENDL << "Decimal Point: " << ado.descriptor.decimal_point;
|
||||
|
||||
add_rollback_event(ptc.height, asset_register_event{ asset_id });
|
||||
WLT_LOG_MAGENTA(ss.str(), LOG_LEVEL_0);
|
||||
if (m_wcallback)
|
||||
m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
//just an update of the asset
|
||||
add_rollback_event(ptc.height, asset_update_event{ it->first, it->second });
|
||||
it->second.asset_descriptor = ado.descriptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (false);
|
||||
|
|
@ -544,7 +588,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
all values m_payments entry, use this strict policy is required to protect exchanges from being feeded with
|
||||
useless outputs
|
||||
*/
|
||||
uint64_t max_out_unlock_time = 0;
|
||||
ptc.max_out_unlock_time = 0;
|
||||
|
||||
std::vector<wallet_out_info> outs;
|
||||
//uint64_t sum_of_native_outs = 0; // TODO: @#@# correctly calculate tx_money_got_in_outs for post-HF4
|
||||
|
|
@ -640,21 +684,29 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
auto it = m_key_images.find(ki);
|
||||
if (it != m_key_images.end())
|
||||
{
|
||||
// Issue that has been discovered by Luke Parker (twitter: @kayabaNerve)
|
||||
// An attacker can quickly issue transaction that use same outputs ephemeral keys + same tx key, as a result both
|
||||
// transaction's outputs would have same key image, so the wallet should have smart approach to this situation, ie
|
||||
// use output that offer biggest output value.(tokens?)
|
||||
|
||||
// We encountered an output with a key image already seen. This implies only one can be spent in the future (assuming the first isn't spent yet).
|
||||
// To address this, we disregard such outputs and log a warning.
|
||||
//
|
||||
// It was later revealed that auditable wallets could still be vulnerable: an attacker might quickly broadcast a transaction
|
||||
// using the same output's ephemeral keys + the same tx pub key. If the malicious transaction (potentially for a lesser amount)
|
||||
// arrives first, the recipient would be unable to spend the funds from the second, real transaction.
|
||||
// This attack vector was highlighted by Luke Parker (twitter: @kayabaNerve), who suggested selecting the output with the largest amount.
|
||||
// Sadly, this fix only applies to classic RingCT transactions and is incompatible with our use of Confidential Assets.
|
||||
// Consequently, we adopted a solution suggested by @crypto_zoidberg: verifying in zero knowledge that the sender possesses the transaction's
|
||||
// secret key. This verification is integrated with the balance proof (double Schnorr proof).
|
||||
//
|
||||
// However, we continue to omit outputs with duplicate key images since they could originate from the same source (albeit impractically).
|
||||
// -- sowle
|
||||
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->second < m_transfers.size(), "m_key_images entry has wrong m_transfers index, it->second: " << it->second << ", m_transfers.size(): " << m_transfers.size());
|
||||
const transfer_details& local_td = m_transfers[it->second];
|
||||
|
||||
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "tx " << ptc.tx_hash() << " @ block " << height << " has output #" << o << " with key image " << ki << " that has already been seen in output #" <<
|
||||
local_td.m_internal_output_index << " in tx " << get_transaction_hash(local_td.m_ptx_wallet_info->m_tx) << " @ block " << local_td.m_spent_height <<
|
||||
". This output can't ever be spent and will be skipped.";
|
||||
ss << "tx " << ptc.tx_hash() << " @ block " << height << " has output #" << o << " with amount " << out.amount;
|
||||
if (!out.is_native_coin())
|
||||
ss << "(asset_id: " << out.asset_id << ") ";
|
||||
ss << "and key image " << ki << " that has already been seen in output #" << local_td.m_internal_output_index << " in tx " << get_transaction_hash(local_td.m_ptx_wallet_info->m_tx)
|
||||
<< " @ block " << local_td.m_spent_height << ". This output can't ever be spent and will be skipped.";
|
||||
WLT_LOG_YELLOW(ss.str(), LOG_LEVEL_0);
|
||||
if (m_wcallback)
|
||||
m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str());
|
||||
|
|
@ -671,9 +723,12 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
out_get_mixin_attr(out_v) != CURRENCY_TO_KEY_OUT_FORCED_NO_MIX)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "output #" << o << " from tx " << ptc.tx_hash() << " with amount " << print_money_brief(outs[i_in_outs].amount)
|
||||
ss << "output #" << o << " from tx " << ptc.tx_hash();
|
||||
if (!out.is_native_coin())
|
||||
ss << " asset_id: " << out.asset_id;
|
||||
ss << " with amount " << print_money_brief(out.amount)
|
||||
<< " is targeted to this auditable wallet and has INCORRECT mix_attr = " << (uint64_t)out_get_mixin_attr(out_v) << ". Output is IGNORED.";
|
||||
WLT_LOG_RED(ss.str(), LOG_LEVEL_0);
|
||||
WLT_LOG_YELLOW(ss.str(), LOG_LEVEL_0);
|
||||
if (m_wcallback)
|
||||
m_wcallback->on_message(i_wallet2_callback::ms_red, ss.str());
|
||||
//if (out.is_native_coin())
|
||||
|
|
@ -777,8 +832,8 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
m_amount_gindex_to_transfer_id[amount_gindex_pair] = transfer_index;
|
||||
}
|
||||
|
||||
if (max_out_unlock_time < get_tx_unlock_time(tx, o))
|
||||
max_out_unlock_time = get_tx_unlock_time(tx, o);
|
||||
if (ptc.max_out_unlock_time < get_tx_unlock_time(tx, o))
|
||||
ptc.max_out_unlock_time = get_tx_unlock_time(tx, o);
|
||||
|
||||
if (out_type_to_key || out_type_zc)
|
||||
{
|
||||
|
|
@ -832,40 +887,12 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
}
|
||||
}
|
||||
|
||||
std::string payment_id;
|
||||
if (has_in_transfers && get_payment_id_from_tx(tx.attachment, payment_id) && payment_id.size())
|
||||
{
|
||||
payment_details payment;
|
||||
payment.m_tx_hash = ptc.tx_hash();
|
||||
payment.m_amount = 0;
|
||||
payment.m_block_height = height;
|
||||
payment.m_unlock_time = max_out_unlock_time;
|
||||
|
||||
for (const auto& bce : ptc.total_balance_change)
|
||||
{
|
||||
if (bce.second > 0)
|
||||
{
|
||||
if (bce.first == currency::native_coin_asset_id)
|
||||
{
|
||||
payment.m_amount = static_cast<uint64_t>(bce.second);
|
||||
}else
|
||||
{
|
||||
payment.subtransfers.push_back(payment_details_subtransfer{ bce.first, static_cast<uint64_t>(bce.second)});
|
||||
}
|
||||
}
|
||||
}
|
||||
m_payments.emplace(payment_id, payment);
|
||||
WLT_LOG_L2("Payment found, id (hex): " << epee::string_tools::buff_to_hex_nodelimer(payment_id) << ", tx: " << payment.m_tx_hash << ", amount: " << print_money_brief(payment.m_amount) << "subtransfers = " << payment.subtransfers.size());
|
||||
}
|
||||
|
||||
if (ptc.spent_own_native_inputs)
|
||||
//check if there are asset_registration that belong to this wallet
|
||||
const asset_descriptor_operation* pado = get_type_in_variant_container<const asset_descriptor_operation>(tx.extra);
|
||||
if (pado && (ptc.employed_entries.receive.size() || ptc.employed_entries.spent.size() || pado->descriptor.owner == m_account.get_public_address().spend_public_key))
|
||||
{
|
||||
//check if there are asset_registration that belong to this wallet
|
||||
asset_descriptor_operation ado = AUTO_VAL_INIT(ado);
|
||||
if (get_type_in_variant_container(tx.extra, ado))
|
||||
{
|
||||
process_ado_in_new_transaction(ado, ptc);
|
||||
}
|
||||
process_ado_in_new_transaction(*pado, ptc);
|
||||
}
|
||||
|
||||
if (has_in_transfers || has_out_transfers || is_derivation_used_to_encrypt(tx, derivation) || ptc.employed_entries.spent.size())
|
||||
|
|
@ -917,7 +944,7 @@ void wallet2::prepare_wti_decrypted_attachments(wallet_public::wallet_transfer_i
|
|||
{
|
||||
LOG_ERROR("wti.payment_id is expected to be empty. Go ahead.");
|
||||
}
|
||||
get_payment_id_from_tx(decrypted_att, wti.payment_id);
|
||||
get_payment_id_from_decrypted_container(decrypted_att, wti.payment_id);
|
||||
|
||||
for (const auto& item : decrypted_att)
|
||||
{
|
||||
|
|
@ -1261,7 +1288,7 @@ bool wallet2::handle_proposal(wallet_public::wallet_transfer_info& wti, const bc
|
|||
ed.is_a = cpd.a_addr.spend_public_key == m_account.get_keys().account_address.spend_public_key;
|
||||
change_contract_state(ed, wallet_public::escrow_contract_details_basic::proposal_sent, ms_id, wti);
|
||||
ed.private_detailes = cpd;
|
||||
currency::get_payment_id_from_tx(decrypted_items, ed.payment_id);
|
||||
currency::get_payment_id_from_decrypted_container(decrypted_items, ed.payment_id);
|
||||
ed.proposal = prop;
|
||||
ed.height = wti.height;
|
||||
wti.contract.resize(1);
|
||||
|
|
@ -1530,8 +1557,42 @@ void wallet2::prepare_wti(wallet_public::wallet_transfer_info& wti, const proces
|
|||
}
|
||||
prepare_wti_decrypted_attachments(wti, decrypted_att);
|
||||
process_contract_info(wti, decrypted_att);
|
||||
process_payment_id_for_wti(wti, tx_process_context);
|
||||
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::process_payment_id_for_wti(wallet_public::wallet_transfer_info& wti, const process_transaction_context& ptc)
|
||||
{
|
||||
//if(this->is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM))
|
||||
{
|
||||
if (wti.get_native_is_income() && wti.payment_id.size())
|
||||
{
|
||||
payment_details payment;
|
||||
payment.m_tx_hash = wti.tx_hash;
|
||||
payment.m_amount = 0;
|
||||
payment.m_block_height = wti.height;
|
||||
payment.m_unlock_time = ptc.max_out_unlock_time;
|
||||
|
||||
for (const auto& bce : ptc.total_balance_change)
|
||||
{
|
||||
if (bce.second > 0)
|
||||
{
|
||||
if (bce.first == currency::native_coin_asset_id)
|
||||
{
|
||||
payment.m_amount = static_cast<uint64_t>(bce.second);
|
||||
}
|
||||
else
|
||||
{
|
||||
payment.subtransfers.push_back(payment_details_subtransfer{ bce.first, static_cast<uint64_t>(bce.second) });
|
||||
}
|
||||
}
|
||||
}
|
||||
m_payments.emplace(wti.payment_id, payment);
|
||||
WLT_LOG_L2("Payment found, id (hex): " << epee::string_tools::buff_to_hex_nodelimer(wti.payment_id) << ", tx: " << payment.m_tx_hash << ", amount: " << print_money_brief(payment.m_amount) << "subtransfers = " << payment.subtransfers.size());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void wallet2::rise_on_transfer2(const wallet_public::wallet_transfer_info& wti)
|
||||
{
|
||||
PROFILE_FUNC("wallet2::rise_on_transfer2");
|
||||
|
|
@ -1582,7 +1643,7 @@ void wallet2::load_wti_from_process_transaction_context(wallet_public::wallet_tr
|
|||
{
|
||||
wti.remote_addresses = tx_process_context.recipients;
|
||||
wti.remote_aliases = tx_process_context.remote_aliases;
|
||||
for (const auto bce : tx_process_context.total_balance_change)
|
||||
for (const auto& bce : tx_process_context.total_balance_change)
|
||||
{
|
||||
wallet_public::wallet_sub_transfer_info wsti = AUTO_VAL_INIT(wsti);
|
||||
wsti.asset_id = bce.first;
|
||||
|
|
@ -3322,7 +3383,7 @@ uint64_t wallet2::balance(uint64_t& unlocked, uint64_t& awaiting_in, uint64_t& a
|
|||
return total;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::balance(crypto::public_key asset_id, uint64_t& unlocked) const
|
||||
uint64_t wallet2::balance(const crypto::public_key& asset_id, uint64_t& unlocked) const
|
||||
{
|
||||
std::unordered_map<crypto::public_key, wallet_public::asset_balance_entry_base> balances;
|
||||
uint64_t dummy;
|
||||
|
|
@ -3336,6 +3397,12 @@ uint64_t wallet2::balance(crypto::public_key asset_id, uint64_t& unlocked) const
|
|||
return it->second.total;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::balance(const crypto::public_key& asset_id) const
|
||||
{
|
||||
uint64_t dummy = 0;
|
||||
return balance(asset_id, dummy);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::balance(std::unordered_map<crypto::public_key, wallet_public::asset_balance_entry_base>& balances, uint64_t& mined) const
|
||||
{
|
||||
mined = 0;
|
||||
|
|
@ -3804,7 +3871,7 @@ void wallet2::submit_transfer(const std::string& signed_tx_blob, currency::trans
|
|||
throw;
|
||||
}
|
||||
|
||||
add_sent_tx_detailed_info(tx, ft.ftp.prepared_destinations, ft.ftp.selected_transfers);
|
||||
add_sent_tx_detailed_info(tx, ft.ftp.attachments, ft.ftp.prepared_destinations, ft.ftp.selected_transfers);
|
||||
m_tx_keys.insert(std::make_pair(tx_hash, ft.one_time_key));
|
||||
|
||||
if (m_watch_only)
|
||||
|
|
@ -4847,7 +4914,7 @@ void wallet2::deploy_new_asset(const currency::asset_descriptor_base& asset_info
|
|||
currency::asset_descriptor_operation ado = AUTO_VAL_INIT(ado);
|
||||
bool r = get_type_in_variant_container(result_tx.extra, ado);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "Failed find asset info in tx");
|
||||
calculate_asset_id(ado.descriptor.owner, nullptr, &new_asset_id);
|
||||
CHECK_AND_ASSERT_THROW_MES(get_or_calculate_asset_id(ado, nullptr, &new_asset_id), "get_or_calculate_asset_id failed");
|
||||
|
||||
m_custom_assets[new_asset_id] = ado.descriptor;
|
||||
}
|
||||
|
|
@ -4871,7 +4938,8 @@ void wallet2::emmit_asset(const crypto::public_key asset_id, std::vector<currenc
|
|||
ctp.dsts = destinations;
|
||||
ctp.extra.push_back(asset_emmit_info);
|
||||
ctp.need_at_least_1_zc = true;
|
||||
ctp.asset_deploy_control_key = own_asset_entry_it->second.control_key;
|
||||
ctp.ado_current_asset_owner = rsp.asset_descriptor.owner;
|
||||
//ctp.asset_deploy_control_key = own_asset_entry_it->second.control_key;
|
||||
|
||||
finalized_tx ft = AUTO_VAL_INIT(ft);
|
||||
this->transfer(ctp, ft, true, nullptr);
|
||||
|
|
@ -4890,7 +4958,33 @@ void wallet2::update_asset(const crypto::public_key asset_id, const currency::as
|
|||
construct_tx_param ctp = get_default_construct_tx_param();
|
||||
ctp.extra.push_back(asset_update_info);
|
||||
ctp.need_at_least_1_zc = true;
|
||||
ctp.asset_deploy_control_key = own_asset_entry_it->second.control_key;
|
||||
currency::asset_descriptor_base adb = AUTO_VAL_INIT(adb);
|
||||
bool r = this->daemon_get_asset_info(asset_id, adb);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "Failed to get asset info from daemon");
|
||||
ctp.ado_current_asset_owner = adb.owner;
|
||||
|
||||
finalized_tx ft = AUTO_VAL_INIT(ft);
|
||||
this->transfer(ctp, ft, true, nullptr);
|
||||
result_tx = ft.tx;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::transfer_asset_ownership(const crypto::public_key asset_id, const crypto::public_key& new_owner, currency::transaction& result_tx)
|
||||
{
|
||||
auto own_asset_entry_it = m_own_asset_descriptors.find(asset_id);
|
||||
CHECK_AND_ASSERT_THROW_MES(own_asset_entry_it != m_own_asset_descriptors.end(), "Failed find asset_id " << asset_id << " in own assets list");
|
||||
|
||||
currency::asset_descriptor_base adb = AUTO_VAL_INIT(adb);
|
||||
bool r = this->daemon_get_asset_info(asset_id, adb);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "Failed to get asset info from daemon");
|
||||
|
||||
asset_descriptor_operation asset_update_info = AUTO_VAL_INIT(asset_update_info);
|
||||
asset_update_info.descriptor = adb;
|
||||
asset_update_info.operation_type = ASSET_DESCRIPTOR_OPERATION_UPDATE;
|
||||
asset_update_info.opt_asset_id = asset_id;
|
||||
asset_update_info.descriptor.owner = new_owner;
|
||||
construct_tx_param ctp = get_default_construct_tx_param();
|
||||
ctp.ado_current_asset_owner = adb.owner;
|
||||
ctp.extra.push_back(asset_update_info);
|
||||
|
||||
finalized_tx ft = AUTO_VAL_INIT(ft);
|
||||
this->transfer(ctp, ft, true, nullptr);
|
||||
|
|
@ -4899,8 +4993,8 @@ void wallet2::update_asset(const crypto::public_key asset_id, const currency::as
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::burn_asset(const crypto::public_key asset_id, uint64_t amount_to_burn, currency::transaction& result_tx)
|
||||
{
|
||||
auto own_asset_entry_it = m_own_asset_descriptors.find(asset_id);
|
||||
CHECK_AND_ASSERT_THROW_MES(own_asset_entry_it != m_own_asset_descriptors.end(), "Failed find asset_id " << asset_id << " in own assets list");
|
||||
//auto own_asset_entry_it = m_own_asset_descriptors.find(asset_id);
|
||||
//CHECK_AND_ASSERT_THROW_MES(own_asset_entry_it != m_own_asset_descriptors.end(), "Failed find asset_id " << asset_id << " in own assets list");
|
||||
COMMAND_RPC_GET_ASSET_INFO::request req;
|
||||
req.asset_id = asset_id;
|
||||
COMMAND_RPC_GET_ASSET_INFO::response rsp;
|
||||
|
|
@ -4923,7 +5017,7 @@ void wallet2::burn_asset(const crypto::public_key asset_id, uint64_t amount_to_b
|
|||
construct_tx_param ctp = get_default_construct_tx_param();
|
||||
ctp.extra.push_back(asset_burn_info);
|
||||
ctp.need_at_least_1_zc = true;
|
||||
ctp.asset_deploy_control_key = own_asset_entry_it->second.control_key;
|
||||
ctp.ado_current_asset_owner = rsp.asset_descriptor.owner;
|
||||
ctp.dsts.push_back(dst_to_burn);
|
||||
|
||||
finalized_tx ft = AUTO_VAL_INIT(ft);
|
||||
|
|
@ -5380,7 +5474,7 @@ void wallet2::send_escrow_proposal(const bc_services::contract_private_details&
|
|||
send_transaction_to_network(tx);
|
||||
|
||||
mark_transfers_as_spent(ftp.selected_transfers, std::string("escrow proposal sent, tx <") + epee::string_tools::pod_to_hex(get_transaction_hash(tx)) + ">, contract: " + epee::string_tools::pod_to_hex(ms_id));
|
||||
add_sent_tx_detailed_info(tx, ftp.prepared_destinations, ftp.selected_transfers);
|
||||
add_sent_tx_detailed_info(tx, ftp.attachments, ftp.prepared_destinations, ftp.selected_transfers);
|
||||
|
||||
print_tx_sent_message(tx, "(from multisig)", fee);
|
||||
}
|
||||
|
|
@ -5548,7 +5642,7 @@ bool wallet2::build_ionic_swap_template(const wallet_public::ionic_swap_proposal
|
|||
proposal.tx_template = finalize_result.tx;
|
||||
wallet_public::ionic_swap_proposal_context ispc = AUTO_VAL_INIT(ispc);
|
||||
ispc.gen_context = finalize_result.ftp.gen_context;
|
||||
ispc.one_time_skey = finalize_result.one_time_key;
|
||||
//ispc.one_time_skey = finalize_result.one_time_key;
|
||||
std::string proposal_context_blob = t_serializable_object_to_blob(ispc);
|
||||
proposal.encrypted_context = crypto::chacha_crypt(static_cast<const std::string&>(proposal_context_blob), finalize_result.derivation);
|
||||
return true;
|
||||
|
|
@ -5586,7 +5680,7 @@ bool wallet2::get_ionic_swap_proposal_info(const wallet_public::ionic_swap_propo
|
|||
r = t_unserializable_object_from_blob(ionic_context, decrypted_raw_context);
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(r, "Failed to unserialize decrypted ionic_context");
|
||||
|
||||
r = validate_tx_output_details_againt_tx_generation_context(tx, ionic_context.gen_context, ionic_context.one_time_skey);
|
||||
r = validate_tx_output_details_againt_tx_generation_context(tx, ionic_context.gen_context);
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(r, "Failed to validate decrypted ionic_context");
|
||||
|
||||
std::unordered_map<crypto::public_key, uint64_t> amounts_provided_by_a;
|
||||
|
|
@ -5754,7 +5848,7 @@ bool wallet2::accept_ionic_swap_proposal(const wallet_public::ionic_swap_proposa
|
|||
construct_tx_param construct_param = get_default_construct_tx_param();
|
||||
construct_param.fee = additional_fee;
|
||||
|
||||
crypto::secret_key one_time_key = ionic_context.one_time_skey;
|
||||
crypto::secret_key one_time_key = ionic_context.gen_context.tx_key.sec; // TODO: figure out this mess with tx sec key -- sowle
|
||||
construct_param.crypt_address = m_account.get_public_address();
|
||||
construct_param.flags = TX_FLAG_SIGNATURE_MODE_SEPARATE;
|
||||
construct_param.mark_tx_as_complete = true;
|
||||
|
|
@ -6250,12 +6344,12 @@ void wallet2::send_transaction_to_network(const transaction& tx)
|
|||
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
void wallet2::add_sent_tx_detailed_info(const transaction& tx,
|
||||
void wallet2::add_sent_tx_detailed_info(const transaction& tx, const std::vector<currency::attachment_v>& decrypted_att,
|
||||
const std::vector<currency::tx_destination_entry>& destinations,
|
||||
const std::vector<uint64_t>& selected_transfers)
|
||||
{
|
||||
payment_id_t payment_id;
|
||||
get_payment_id_from_tx(tx.attachment, payment_id);
|
||||
get_payment_id_from_decrypted_container(decrypted_att, payment_id);
|
||||
|
||||
std::vector<std::string> recipients;
|
||||
std::unordered_set<account_public_address> used_addresses;
|
||||
|
|
@ -6916,7 +7010,8 @@ bool wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx
|
|||
|
||||
const currency::transaction& tx_for_mode_separate = msc.tx_for_mode_separate;
|
||||
assets_selection_context needed_money_map = get_needed_money(ctp.fee, ctp.dsts);
|
||||
ftp.asset_control_key = ctp.asset_deploy_control_key;
|
||||
ftp.ado_current_asset_owner = ctp.ado_current_asset_owner;
|
||||
ftp.pthirdparty_sign_handler = ctp.pthirdparty_sign_handler;
|
||||
//
|
||||
// TODO @#@# need to do refactoring over this part to support hidden amounts and asset_id
|
||||
//
|
||||
|
|
@ -7057,7 +7152,7 @@ void wallet2::finalize_transaction(currency::finalize_tx_param& ftp, currency::f
|
|||
|
||||
//TIME_MEASURE_START(add_sent_tx_detailed_info_time);
|
||||
if (broadcast_tx)
|
||||
add_sent_tx_detailed_info(result.tx, ftp.prepared_destinations, ftp.selected_transfers);
|
||||
add_sent_tx_detailed_info(result.tx, ftp.attachments, ftp.prepared_destinations, ftp.selected_transfers);
|
||||
//TIME_MEASURE_FINISH(add_sent_tx_detailed_info_time);
|
||||
|
||||
/* TODO
|
||||
|
|
@ -7181,7 +7276,7 @@ void wallet2::check_and_throw_if_self_directed_tx_with_payment_id_requested(cons
|
|||
|
||||
// it's self-directed tx
|
||||
payment_id_t pid;
|
||||
bool has_payment_id = get_payment_id_from_tx(ctp.attachments, pid) && !pid.empty();
|
||||
bool has_payment_id = get_payment_id_from_decrypted_container(ctp.attachments, pid) && !pid.empty();
|
||||
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(!has_payment_id, "sending funds to yourself with payment id is not allowed");
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
@ -7331,8 +7426,9 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public
|
|||
|
||||
currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
|
||||
ftp.tx_version = this->get_current_tx_version();
|
||||
bool is_hf4 = this->is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM);
|
||||
if (!payment_id.empty())
|
||||
set_payment_id_to_tx(ftp.attachments, payment_id);
|
||||
set_payment_id_to_tx(ftp.attachments, payment_id, is_hf4);
|
||||
// put encrypted payer info into the extra
|
||||
ftp.crypt_address = destination_addr;
|
||||
|
||||
|
|
|
|||
|
|
@ -323,6 +323,7 @@ namespace tools
|
|||
multisig_entries_map* pmultisig_entries = nullptr;
|
||||
crypto::public_key tx_pub_key = currency::null_pkey;
|
||||
uint64_t tx_expiration_ts_median = 0;
|
||||
uint64_t max_out_unlock_time = 0;
|
||||
|
||||
const crypto::hash& tx_hash() const
|
||||
{
|
||||
|
|
@ -391,9 +392,10 @@ namespace tools
|
|||
void emmit_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 transfer_asset_ownership(const crypto::public_key asset_id, const crypto::public_key& new_owner, currency::transaction& result_tx);
|
||||
|
||||
bool daemon_get_asset_info(const crypto::public_key& asset_id, currency::asset_descriptor_base& adb);
|
||||
|
||||
const std::unordered_map<crypto::public_key, wallet_own_asset_context>& get_own_assets() const { return m_own_asset_descriptors; }
|
||||
bool set_core_proxy(const std::shared_ptr<i_core_proxy>& proxy);
|
||||
void set_pos_utxo_count_limits_for_defragmentation_tx(uint64_t min_outs, uint64_t max_outs); // don't create UTXO defrag. tx if there are less than 'min_outs' outs; don't put more than 'max_outs' outs
|
||||
void set_pos_decoys_count_for_defragmentation_tx(size_t decoys_count);
|
||||
|
|
@ -404,7 +406,8 @@ namespace tools
|
|||
uint64_t balance(uint64_t& unloked, uint64_t& awaiting_in, uint64_t& awaiting_out, uint64_t& mined, const crypto::public_key& asset_id = currency::native_coin_asset_id) const;
|
||||
bool balance(std::unordered_map<crypto::public_key, wallet_public::asset_balance_entry_base>& balances, uint64_t& mined) const;
|
||||
bool balance(std::list<wallet_public::asset_balance_entry>& balances, uint64_t& mined) const;
|
||||
uint64_t balance(crypto::public_key asset_id, uint64_t& unloked) const;
|
||||
uint64_t balance(const crypto::public_key& asset_id, uint64_t& unlocked) const;
|
||||
uint64_t balance(const crypto::public_key& asset_id) const;
|
||||
|
||||
uint64_t balance(uint64_t& unloked) const;
|
||||
|
||||
|
|
@ -688,6 +691,7 @@ namespace tools
|
|||
bool validate_sign(const std::string& buff, const crypto::signature& sig, const crypto::public_key& pkey);
|
||||
bool encrypt_buffer(const std::string& buff, std::string& res_buff);
|
||||
bool decrypt_buffer(const std::string& buff, std::string& res_buff);
|
||||
bool is_in_hardfork_zone(uint64_t hardfork_index) const;
|
||||
|
||||
construct_tx_param get_default_construct_tx_param();
|
||||
|
||||
|
|
@ -739,6 +743,7 @@ private:
|
|||
void prepare_wti_decrypted_attachments(wallet_public::wallet_transfer_info& wti, const std::vector<currency::payload_items_v>& decrypted_att);
|
||||
void handle_money(const currency::block& b, const process_transaction_context& tx_process_context);
|
||||
void load_wti_from_process_transaction_context(wallet_public::wallet_transfer_info& wti, const process_transaction_context& tx_process_context);
|
||||
bool process_payment_id_for_wti(wallet_public::wallet_transfer_info& wti, const process_transaction_context& tx_process_context);
|
||||
|
||||
void handle_pulled_blocks(size_t& blocks_added, std::atomic<bool>& stop,
|
||||
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& blocks);
|
||||
|
|
@ -815,7 +820,8 @@ private:
|
|||
void load_keys2ki(bool create_if_not_exist, bool& need_to_resync);
|
||||
|
||||
void send_transaction_to_network(const currency::transaction& tx);
|
||||
void add_sent_tx_detailed_info(const currency::transaction& tx,
|
||||
void add_sent_tx_detailed_info(const currency::transaction& tx,
|
||||
const std::vector<currency::attachment_v>& decrypted_att,
|
||||
const std::vector<currency::tx_destination_entry>& destinations,
|
||||
const std::vector<uint64_t>& selected_indicies);
|
||||
void mark_transfers_as_spent(const std::vector<uint64_t>& selected_transfers, const std::string& reason = std::string());
|
||||
|
|
@ -836,7 +842,6 @@ private:
|
|||
uint64_t get_directly_spent_transfer_index_by_input_in_tracking_wallet(uint64_t amount, const std::vector<currency::txout_ref_v> & key_offsets);
|
||||
uint64_t get_directly_spent_transfer_index_by_input_in_tracking_wallet(const currency::txin_to_key& intk);
|
||||
uint64_t get_directly_spent_transfer_index_by_input_in_tracking_wallet(const currency::txin_zc_input& inzc);
|
||||
bool is_in_hardfork_zone(uint64_t hardfork_index) const;
|
||||
uint8_t out_get_mixin_attr(const currency::tx_out_v& out_t);
|
||||
const crypto::public_key& out_get_pub_key(const currency::tx_out_v& out_t, std::list<currency::htlc_info>& htlc_info_list);
|
||||
bool expand_selection_with_zc_input(assets_selection_context& needed_money_map, uint64_t fake_outputs_count, std::vector<uint64_t>& selected_indexes);
|
||||
|
|
|
|||
|
|
@ -199,6 +199,7 @@ namespace tools
|
|||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
|
||||
struct construct_tx_param
|
||||
{
|
||||
// preparing data for tx
|
||||
|
|
@ -223,7 +224,9 @@ namespace tools
|
|||
bool shuffle = false;
|
||||
bool create_utxo_defragmentation_tx = false;
|
||||
bool need_at_least_1_zc = false;
|
||||
crypto::secret_key asset_deploy_control_key = currency::null_skey;
|
||||
//crypto::secret_key asset_deploy_control_key = currency::null_skey;
|
||||
currency::thirdparty_sign_handler* pthirdparty_sign_handler = nullptr;
|
||||
crypto::public_key ado_current_asset_owner = currency::null_pkey;
|
||||
};
|
||||
|
||||
struct mode_separate_context
|
||||
|
|
@ -255,13 +258,11 @@ namespace tools
|
|||
struct wallet_own_asset_context
|
||||
{
|
||||
currency::asset_descriptor_base asset_descriptor;
|
||||
crypto::secret_key control_key;
|
||||
//uint64_t height = 0;
|
||||
bool thirdparty_custody = false;
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
BOOST_SERIALIZE(asset_descriptor)
|
||||
BOOST_SERIALIZE(control_key)
|
||||
//BOOST_SERIALIZE(height)
|
||||
BOOST_SERIALIZE(thirdparty_custody)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,20 @@ struct wde_construct_tx_handle_asset_descriptor_operation
|
|||
};
|
||||
|
||||
|
||||
//Wallet Debug Events
|
||||
struct wde_construct_tx_handle_asset_descriptor_operation_before_seal
|
||||
{
|
||||
currency::asset_descriptor_operation* pado;
|
||||
};
|
||||
|
||||
struct wde_construct_tx_handle_asset_descriptor_operation_before_burn
|
||||
{
|
||||
currency::asset_descriptor_operation* pado;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct wde_construct_tx_after_asset_ownership_proof_generated
|
||||
{
|
||||
currency::asset_operation_ownership_proof* pownership_proof;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -273,18 +273,28 @@ namespace wallet_public
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
struct wallet_transfer_info_old : public wallet_transfer_info
|
||||
{
|
||||
uint64_t amount = 0;
|
||||
bool is_income = false;
|
||||
//uint64_t amount = 0;
|
||||
//bool is_income = false;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(is_income)
|
||||
KV_SERIALIZE(amount)
|
||||
KV_SERIALIZE_EPHEMERAL_N(uint64_t, wallet_transfer_info_to_amount, "amount")
|
||||
KV_SERIALIZE_EPHEMERAL_N(bool, wallet_transfer_info_to_is_income, "is_income")
|
||||
//KV_SERIALIZE(amount)
|
||||
KV_CHAIN_BASE(wallet_transfer_info)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
static uint64_t wallet_transfer_info_to_amount(const wallet_transfer_info_old& wtio)
|
||||
{
|
||||
return wtio.get_native_amount();
|
||||
}
|
||||
|
||||
static bool wallet_transfer_info_to_is_income(const wallet_transfer_info_old& wtio)
|
||||
{
|
||||
return wtio.get_native_is_income();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1226,6 +1236,29 @@ namespace wallet_public
|
|||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_SEARCH_FOR_TRANSACTIONS_LEGACY
|
||||
{
|
||||
typedef COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::request request;
|
||||
|
||||
struct response
|
||||
{
|
||||
std::list<wallet_transfer_info_old> in;
|
||||
std::list<wallet_transfer_info_old> out;
|
||||
//std::list<wallet_transfer_info> pending;
|
||||
//std::list<wallet_transfer_info> failed;
|
||||
std::list<wallet_transfer_info_old> pool;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(in)
|
||||
KV_SERIALIZE(out)
|
||||
//KV_SERIALIZE(pending)
|
||||
//KV_SERIALIZE(failed)
|
||||
KV_SERIALIZE(pool)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct htlc_entry_info
|
||||
{
|
||||
currency::account_public_address counterparty_address;
|
||||
|
|
@ -1407,12 +1440,10 @@ namespace wallet_public
|
|||
struct ionic_swap_proposal_context
|
||||
{
|
||||
currency::tx_generation_context gen_context;
|
||||
crypto::secret_key one_time_skey;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
VERSION(0) //use VERSION_TO_MEMBER if it's more then 0
|
||||
FIELD(gen_context)
|
||||
FIELD(one_time_skey)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -276,6 +276,16 @@ namespace tools
|
|||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
template<typename t_from, typename t_to>
|
||||
void copy_wallet_transfer_info_old_container(const t_from& from_c, t_to& to_c)
|
||||
{
|
||||
for (const auto& item : from_c)
|
||||
{
|
||||
to_c.push_back(wallet_public::wallet_transfer_info_old());
|
||||
*static_cast<wallet_public::wallet_transfer_info*>(&to_c.back()) = item;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_get_recent_txs_and_info(const wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::request& req, wallet_public::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
//this is legacy api, should be removed after successful transition to HF4
|
||||
|
|
@ -286,20 +296,7 @@ namespace tools
|
|||
res.pi = rsp2.pi;
|
||||
res.total_transfers = rsp2.total_transfers;
|
||||
res.last_item_index = rsp2.last_item_index;
|
||||
for (const auto& item : rsp2.transfers)
|
||||
{
|
||||
res.transfers.push_back(wallet_public::wallet_transfer_info_old());
|
||||
*static_cast<wallet_public::wallet_transfer_info*>(&res.transfers.back()) = item;
|
||||
for (const auto& subitem : item.subtransfers)
|
||||
{
|
||||
if (subitem.asset_id == currency::native_coin_asset_id)
|
||||
{
|
||||
res.transfers.back().amount = subitem.amount;
|
||||
res.transfers.back().is_income = subitem.is_income;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
copy_wallet_transfer_info_old_container(rsp2.transfers, res.transfers);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
|
|
@ -413,7 +410,7 @@ namespace tools
|
|||
|
||||
std::vector<currency::attachment_v>& attachments = ctp.attachments;
|
||||
std::vector<currency::extra_v>& extra = ctp.extra;
|
||||
if (!payment_id.empty() && !currency::set_payment_id_to_tx(attachments, payment_id))
|
||||
if (!payment_id.empty() && !currency::set_payment_id_to_tx(attachments, payment_id, w.get_wallet()->is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM)))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
|
||||
er.message = std::string("payment id ") + payment_id + " is invalid and can't be set";
|
||||
|
|
@ -699,8 +696,19 @@ namespace tools
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wallet_rpc_server::on_search_for_transactions(const wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS_LEGACY::request& req, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS_LEGACY::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::response res_origin;
|
||||
bool r = this->on_search_for_transactions2(req, res_origin, er, cntx);
|
||||
copy_wallet_transfer_info_old_container(res_origin.in, res.in);
|
||||
copy_wallet_transfer_info_old_container(res_origin.out, res.out);
|
||||
copy_wallet_transfer_info_old_container(res_origin.pool, res.pool);
|
||||
|
||||
return r;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_search_for_transactions(const wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::request& req, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
bool wallet_rpc_server::on_search_for_transactions2(const wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::request& req, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
bool tx_id_specified = req.tx_id != currency::null_hash;
|
||||
|
|
@ -753,6 +761,7 @@ namespace tools
|
|||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_get_mining_history(const wallet_public::COMMAND_RPC_GET_MINING_HISTORY::request& req, wallet_public::COMMAND_RPC_GET_MINING_HISTORY::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
|
|
|||
|
|
@ -105,7 +105,8 @@ namespace tools
|
|||
MAP_JON_RPC_WE("sweep_below", on_sweep_below, wallet_public::COMMAND_SWEEP_BELOW)
|
||||
MAP_JON_RPC_WE("sign_transfer", on_sign_transfer, wallet_public::COMMAND_SIGN_TRANSFER)
|
||||
MAP_JON_RPC_WE("submit_transfer", on_submit_transfer, wallet_public::COMMAND_SUBMIT_TRANSFER)
|
||||
MAP_JON_RPC_WE("search_for_transactions", on_search_for_transactions, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS)
|
||||
MAP_JON_RPC_WE("search_for_transactions", on_search_for_transactions, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS_LEGACY)
|
||||
MAP_JON_RPC_WE("search_for_transactions2", on_search_for_transactions2, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS)
|
||||
MAP_JON_RPC_WE("get_restore_info", on_getwallet_restore_info, wallet_public::COMMAND_RPC_GET_WALLET_RESTORE_INFO)
|
||||
MAP_JON_RPC_WE("get_seed_phrase_info", on_get_seed_phrase_info, wallet_public::COMMAND_RPC_GET_SEED_PHRASE_INFO)
|
||||
MAP_JON_RPC_WE("get_mining_history", on_get_mining_history, wallet_public::COMMAND_RPC_GET_MINING_HISTORY)
|
||||
|
|
@ -161,7 +162,8 @@ namespace tools
|
|||
bool on_sweep_below(const wallet_public::COMMAND_SWEEP_BELOW::request& req, wallet_public::COMMAND_SWEEP_BELOW::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_sign_transfer(const wallet_public::COMMAND_SIGN_TRANSFER::request& req, wallet_public::COMMAND_SIGN_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_submit_transfer(const wallet_public::COMMAND_SUBMIT_TRANSFER::request& req, wallet_public::COMMAND_SUBMIT_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_search_for_transactions(const wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::request& req, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_search_for_transactions(const wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS_LEGACY::request& req, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS_LEGACY::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_search_for_transactions2(const wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::request& req, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_get_mining_history(const wallet_public::COMMAND_RPC_GET_MINING_HISTORY::request& req, wallet_public::COMMAND_RPC_GET_MINING_HISTORY::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_register_alias(const wallet_public::COMMAND_RPC_REGISTER_ALIAS::request& req, wallet_public::COMMAND_RPC_REGISTER_ALIAS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ bool wallets_manager::init_command_line(int argc, char* argv[], std::string& fai
|
|||
command_line::add_arg(desc_cmd_sett, arg_qt_dev_tools);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_no_predownload);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_force_predownload);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_process_predownload_from_path);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_validate_predownload);
|
||||
command_line::add_arg(desc_cmd_sett, command_line::arg_predownload_link);
|
||||
command_line::add_arg(desc_cmd_only, command_line::arg_deeplink);
|
||||
|
|
@ -1533,18 +1534,17 @@ std::string wallets_manager::transfer(uint64_t wallet_id, const view::transfer_p
|
|||
dsts.back().asset_id = d.asset_id;
|
||||
}
|
||||
|
||||
GET_WALLET_BY_ID(wallet_id, w);
|
||||
|
||||
if (payment_id.size())
|
||||
{
|
||||
if (!currency::is_payment_id_size_ok(payment_id))
|
||||
return API_RETURN_CODE_BAD_ARG_WRONG_PAYMENT_ID; // payment id is too big
|
||||
|
||||
if (!currency::set_payment_id_to_tx(attachments, payment_id))
|
||||
if (!currency::set_payment_id_to_tx(attachments, payment_id, w->get()->is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM)))
|
||||
return API_RETURN_CODE_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
GET_WALLET_BY_ID(wallet_id, w);
|
||||
|
||||
|
||||
|
||||
//set transaction unlock time if it was specified by user
|
||||
uint64_t unlock_time = 0;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ add_executable(net_load_tests_srv net_load_tests/srv.cpp)
|
|||
|
||||
add_dependencies(coretests version)
|
||||
|
||||
target_link_libraries(coretests rpc wallet currency_core common crypto zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(coretests rpc wallet currency_core common crypto zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
target_link_libraries(functional_tests rpc wallet currency_core crypto common zlibstatic ethash libminiupnpc-static ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(hash-tests crypto ethash)
|
||||
target_link_libraries(hash-target-tests crypto currency_core ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
|
|
|
|||
|
|
@ -1055,6 +1055,7 @@ bool test_generator::construct_pow_block_with_alias_info_in_coinbase(const accou
|
|||
miner_tx.vout.clear();
|
||||
|
||||
tx_generation_context tx_gen_context{};
|
||||
tx_gen_context.set_tx_key(tx_key);
|
||||
tx_gen_context.resize(/* ZC ins: */ 0, /* OUTS: */ alias_cost != 0 ? 3 : 2);
|
||||
std::set<unsigned short> deriv_cache;
|
||||
finalized_tx fin_tx_stub{};
|
||||
|
|
|
|||
|
|
@ -1085,6 +1085,7 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(wallet_rpc_integrated_address);
|
||||
GENERATE_AND_PLAY(wallet_rpc_integrated_address_transfer);
|
||||
GENERATE_AND_PLAY(wallet_rpc_transfer);
|
||||
GENERATE_AND_PLAY_HF(wallet_rpc_exchange_suite, "3,4");
|
||||
GENERATE_AND_PLAY(wallet_chain_switch_with_spending_the_same_ki);
|
||||
GENERATE_AND_PLAY(wallet_sending_to_integrated_address);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,65 +11,6 @@
|
|||
#include "wallet/wallet_debug_events_definitions.h"
|
||||
using namespace currency;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
||||
struct debug_context_event_1
|
||||
{
|
||||
int& i;
|
||||
std::string& s;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//#define RAISE_DEBUG_EVENT dw.handle_type
|
||||
|
||||
|
||||
void test_test()
|
||||
{
|
||||
epee::misc_utils::events_dispatcher ed;
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------
|
||||
//thus code will be called in the tests
|
||||
ed.SUBSCIRBE_DEBUG_EVENT<debug_context_event_1>([&](debug_context_event_1& d)
|
||||
{
|
||||
//here some operations
|
||||
LOG_PRINT_L0("lala: " << d.i << d.s);
|
||||
//
|
||||
d.i = 10;
|
||||
d.s = "33333";
|
||||
|
||||
});
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------
|
||||
//this code will be in the wallet and helper functions
|
||||
|
||||
int i = 22;
|
||||
std::string sss = "11111";
|
||||
|
||||
ed.RAISE_DEBUG_EVENT(debug_context_event_1{i, sss });
|
||||
|
||||
|
||||
LOG_PRINT_L0("lala: " << i << sss);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#define AMOUNT_TO_TRANSFER_MULTIASSETS_BASIC (TESTS_DEFAULT_FEE)
|
||||
|
|
@ -97,6 +38,7 @@ bool multiassets_basic_test::generate(std::vector<test_event_entry>& events) con
|
|||
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
|
||||
//TODO: Need to make sure REWIND_BLOCKS_N and other coretests codebase are capable of following hardfork4 rules
|
||||
//in this test hardfork4 moment moved to runtime section
|
||||
//REWIND_BLOCKS_N_WITH_TIME(events, blk_2_inital, blk_0, alice_acc, 2);
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
|
@ -115,7 +57,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
alice_wlt->get_account().set_createtime(0);
|
||||
|
||||
asset_descriptor_base adb = AUTO_VAL_INIT(adb);
|
||||
adb.total_max_supply = 1000000000000000000; //1M coins
|
||||
adb.total_max_supply = 10000000000000000000ULL; //1M coins
|
||||
adb.full_name = "Test coins";
|
||||
adb.ticker = "TCT";
|
||||
adb.decimal_point = 12;
|
||||
|
|
@ -141,31 +83,13 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
|
||||
miner_wlt->refresh();
|
||||
alice_wlt->refresh();
|
||||
uint64_t mined = 0;
|
||||
std::unordered_map<crypto::public_key, tools::wallet_public::asset_balance_entry_base> balances;
|
||||
miner_wlt->balance(balances, mined);
|
||||
CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id) == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances");
|
||||
CHECK_AND_ASSERT_MES(miner_wlt->balance() == uint64_t(17517225990000000000ULL), false, "Failed to find needed asset in result balances");
|
||||
|
||||
auto it_asset = balances.find(asset_id);
|
||||
auto it_native = balances.find(currency::native_coin_asset_id);
|
||||
|
||||
|
||||
CHECK_AND_ASSERT_MES(it_asset != balances.end() && it_native != balances.end(), false, "Failed to find needed asset in result balances");
|
||||
CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances");
|
||||
CHECK_AND_ASSERT_MES(it_native->second.total == uint64_t(17517225990000000000), false, "Failed to find needed asset in result balances");
|
||||
|
||||
|
||||
balances.clear();
|
||||
alice_wlt->balance(balances, mined);
|
||||
|
||||
it_asset = balances.find(asset_id);
|
||||
it_native = balances.find(currency::native_coin_asset_id);
|
||||
|
||||
CHECK_AND_ASSERT_MES(it_asset != balances.end(), false, "Failed to find needed asset in result balances");
|
||||
CHECK_AND_ASSERT_MES(it_native == balances.end(), false, "Failed to find needed asset in result balances");
|
||||
CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances");
|
||||
CHECK_AND_ASSERT_MES(alice_wlt->balance() == 0, false, "Failed to find needed asset in result balances");
|
||||
CHECK_AND_ASSERT_MES(alice_wlt->balance(asset_id) == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances");
|
||||
|
||||
miner_wlt->transfer(AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC/2, alice_wlt->get_account().get_public_address(), asset_id);
|
||||
//pass over hardfork
|
||||
|
|
@ -173,11 +97,9 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
alice_wlt->refresh();
|
||||
uint64_t last_alice_balances = alice_wlt->balance(asset_id, mined);
|
||||
uint64_t last_alice_balances = alice_wlt->balance(asset_id);
|
||||
CHECK_AND_ASSERT_MES(last_alice_balances == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC + AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC/2, false, "Failed to find needed asset in result balances");
|
||||
|
||||
|
||||
|
||||
{
|
||||
try {
|
||||
|
||||
|
|
@ -193,7 +115,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
}
|
||||
|
||||
miner_wlt->refresh();
|
||||
uint64_t last_miner_balance = miner_wlt->balance(asset_id, mined);
|
||||
uint64_t last_miner_balance = miner_wlt->balance(asset_id);
|
||||
|
||||
|
||||
asset_descriptor_base asset_info = AUTO_VAL_INIT(asset_info);
|
||||
|
|
@ -211,7 +133,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
//test update function
|
||||
asset_info.meta_info = "{\"some\": \"info\"}";
|
||||
miner_wlt->update_asset(asset_id, asset_info, tx);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 2);
|
||||
r = mine_next_pow_blocks_in_playtime(alice_wlt->get_account().get_public_address(), c, 2);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
asset_descriptor_base asset_info2 = AUTO_VAL_INIT(asset_info2);
|
||||
|
|
@ -228,8 +150,8 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
|
||||
miner_wlt->refresh();
|
||||
alice_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id, mined) == last_miner_balance + destinations[0].amount, false, "Miner balance wrong");
|
||||
CHECK_AND_ASSERT_MES(alice_wlt->balance(asset_id, mined) == last_alice_balances + destinations[1].amount, false, "Alice balance wrong");
|
||||
CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id) == last_miner_balance + destinations[0].amount, false, "Miner balance wrong");
|
||||
CHECK_AND_ASSERT_MES(alice_wlt->balance(asset_id) == last_alice_balances + destinations[1].amount, false, "Alice balance wrong");
|
||||
|
||||
asset_descriptor_base asset_info3 = AUTO_VAL_INIT(asset_info3);
|
||||
r = c.get_blockchain_storage().get_asset_info(asset_id, asset_info3);
|
||||
|
|
@ -242,7 +164,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 1);
|
||||
|
||||
miner_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id, mined) == destinations[0].amount, false, "Miner balance wrong");
|
||||
CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id) == destinations[0].amount, false, "Miner balance wrong");
|
||||
|
||||
asset_descriptor_base asset_info4 = AUTO_VAL_INIT(asset_info4);
|
||||
r = c.get_blockchain_storage().get_asset_info(asset_id, asset_info4);
|
||||
|
|
@ -252,10 +174,10 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
|
||||
//------------------- tests that trying to break stuff -------------------
|
||||
//tests that trying to break stuff
|
||||
miner_wlt->get_debug_events_dispatcher().SUBSCIRBE_DEBUG_EVENT<wde_construct_tx_handle_asset_descriptor_operation>([&](const wde_construct_tx_handle_asset_descriptor_operation& o)
|
||||
miner_wlt->get_debug_events_dispatcher().SUBSCIRBE_DEBUG_EVENT<wde_construct_tx_after_asset_ownership_proof_generated>([&](const wde_construct_tx_after_asset_ownership_proof_generated& o)
|
||||
{
|
||||
crypto::signature s = currency::null_sig;
|
||||
o.pado->opt_proof = s;
|
||||
//crypto::signature s = currency::null_sig;
|
||||
o.pownership_proof->gss = crypto::generic_schnorr_sig_s{};
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -270,7 +192,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
c.get_tx_pool().purge_transactions();
|
||||
miner_wlt->refresh();
|
||||
|
||||
miner_wlt->get_debug_events_dispatcher().UNSUBSCRIBE_DEBUG_EVENT<wde_construct_tx_handle_asset_descriptor_operation>();
|
||||
miner_wlt->get_debug_events_dispatcher().UNSUBSCRIBE_ALL();
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
|
||||
|
|
@ -317,17 +239,17 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
|
||||
|
||||
// check update_asset() with modified 'owner'
|
||||
r = c.get_blockchain_storage().get_asset_info(asset_id, asset_info);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to get_asset_info");
|
||||
//r = c.get_blockchain_storage().get_asset_info(asset_id, asset_info);
|
||||
//CHECK_AND_ASSERT_MES(r, false, "Failed to get_asset_info");
|
||||
|
||||
asset_info.owner = currency::keypair::generate().pub;
|
||||
miner_wlt->update_asset(asset_id, asset_info, tx);
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c);
|
||||
CHECK_AND_ASSERT_MES(!r, false, "block with a bad tx was unexpectedly mined");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not confirmed
|
||||
c.get_tx_pool().purge_transactions();
|
||||
miner_wlt->refresh();
|
||||
//asset_info.owner = currency::keypair::generate().pub;
|
||||
//miner_wlt->update_asset(asset_id, asset_info, tx);
|
||||
//CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
//r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c);
|
||||
//CHECK_AND_ASSERT_MES(!r, false, "block with a bad tx was unexpectedly mined");
|
||||
//CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not confirmed
|
||||
//c.get_tx_pool().purge_transactions();
|
||||
//miner_wlt->refresh();
|
||||
|
||||
|
||||
// check emmit_asset() with modified 'current_supply'
|
||||
|
|
@ -346,13 +268,14 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
|
||||
//------------------- tests that trying to break stuff -------------------
|
||||
//test burn that burns more than tx has
|
||||
miner_wlt->get_debug_events_dispatcher().UNSUBSCRIBE_DEBUG_EVENT<wde_construct_tx_handle_asset_descriptor_operation_before_seal>();
|
||||
miner_wlt->get_debug_events_dispatcher().UNSUBSCRIBE_ALL();
|
||||
|
||||
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)
|
||||
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;
|
||||
});
|
||||
|
||||
|
||||
miner_wlt->burn_asset(asset_id, 10000000000000, tx);
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c);
|
||||
|
|
@ -360,8 +283,39 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not confirmed
|
||||
c.get_tx_pool().purge_transactions();
|
||||
miner_wlt->refresh();
|
||||
miner_wlt->get_debug_events_dispatcher().UNSUBSCRIBE_ALL();
|
||||
|
||||
//
|
||||
miner_wlt->transfer_asset_ownership(asset_id, alice_wlt->get_account().get_public_address().spend_public_key, tx);
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c);
|
||||
CHECK_AND_ASSERT_MES(r, false, "block with a bad tx was unexpectedly mined");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not confirmed
|
||||
|
||||
miner_wlt->refresh();
|
||||
alice_wlt->refresh();
|
||||
|
||||
auto miner_own_assets = miner_wlt->get_own_assets();
|
||||
auto alice_own_assets = alice_wlt->get_own_assets();
|
||||
CHECK_AND_ASSERT_MES(miner_own_assets.size() == 0, false, "Miner wlt still think he own asset");
|
||||
CHECK_AND_ASSERT_MES(alice_own_assets.size() == 1, false, "Alice still don't know she own asset");
|
||||
|
||||
//uint64_t balance_alice_native = alice_wlt->balance();
|
||||
//uint64_t balance_miner_native = miner_wlt->balance();
|
||||
uint64_t balance_alice_asset = alice_wlt->balance(asset_id);
|
||||
uint64_t balance_miner_asset = miner_wlt->balance(asset_id);
|
||||
|
||||
alice_wlt->emmit_asset(asset_id, destinations, tx);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
miner_wlt->refresh();
|
||||
alice_wlt->refresh();
|
||||
|
||||
CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id) == balance_miner_asset + destinations[0].amount, false, "Miner balance wrong");
|
||||
CHECK_AND_ASSERT_MES(alice_wlt->balance(asset_id) == balance_alice_asset + destinations[1].amount, false, "Alice balance wrong");
|
||||
|
||||
//TODO: attempt to emmmit from old key, attempt to emmit from more then max supply
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -432,7 +386,7 @@ bool assets_and_explicit_native_coins_in_outs::generate(std::vector<test_event_e
|
|||
MAKE_TX(events, tx_1, alice_acc, alice_acc, m_alice_initial_balance - TESTS_DEFAULT_FEE, blk_1r);
|
||||
CHECK_AND_ASSERT_MES(tx_1.vout.size() == 2, false, "unexpected tx_1.vout.size : " << tx_1.vout.size());
|
||||
|
||||
// make sure that all tx_1 outputs have explicit hative coin asset id
|
||||
// make sure that all tx_1 outputs have explicit native coin asset id
|
||||
for(auto& out : tx_1.vout)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(out.type() == typeid(tx_out_zarcanum), false, "invalid out type");
|
||||
|
|
|
|||
|
|
@ -298,5 +298,384 @@ bool wallet_rpc_transfer::c1(currency::core& c, size_t ev_index, const std::vect
|
|||
CHECK_AND_ASSERT_MES(currency::count_type_in_variant_container<tx_payer>(pche->tx.extra) == 1, false, "tx_payer: incorrect count of items");
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
wallet_rpc_exchange_suite::wallet_rpc_exchange_suite()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(wallet_rpc_exchange_suite, c1);
|
||||
}
|
||||
|
||||
bool wallet_rpc_exchange_suite::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate();
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());
|
||||
DO_CALLBACK(events, "configure_core"); // default callback will initialize core runtime config with m_hardforks
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
struct transport
|
||||
{
|
||||
tools::wallet_rpc_server& m_rpc_srv;
|
||||
transport(tools::wallet_rpc_server& rpc_srv):m_rpc_srv(rpc_srv)
|
||||
{}
|
||||
epee::net_utils::http::http_response_info m_response;
|
||||
|
||||
bool is_connected() { return true; }
|
||||
template<typename t_a, typename t_b, typename t_c>
|
||||
bool connect(t_a ta, t_b tb, t_c tc) { return true; }
|
||||
|
||||
template<typename dummy_t>
|
||||
bool invoke(const std::string uri, const std::string method_, const std::string& body, const epee::net_utils::http::http_response_info** ppresponse_info, const dummy_t& d)
|
||||
{
|
||||
epee::net_utils::http::http_request_info query_info;
|
||||
query_info.m_URI = uri;
|
||||
query_info.m_body = body;
|
||||
tools::wallet_rpc_server::connection_context ctx;
|
||||
bool r = m_rpc_srv.handle_http_request(query_info, m_response, ctx);
|
||||
if (ppresponse_info)
|
||||
*ppresponse_info = &m_response;
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename request_t, typename response_t>
|
||||
bool invoke_text_json_for_rpc(tools::wallet_rpc_server& srv, const std::string& method_name, const request_t& req, response_t& resp)
|
||||
{
|
||||
transport tr(srv);
|
||||
|
||||
bool r = epee::net_utils::invoke_http_json_rpc("/json_rpc", method_name, req, resp, tr);
|
||||
return r;
|
||||
}
|
||||
|
||||
#include "wallet_rpc_tests_legacy_defs.h"
|
||||
|
||||
|
||||
std::string gen_payment_id(tools::wallet_rpc_server& custody_wlt_rpc)
|
||||
{
|
||||
pre_hf4_api::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::request req = AUTO_VAL_INIT(req);
|
||||
pre_hf4_api::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::response resp = AUTO_VAL_INIT(resp);
|
||||
bool r = invoke_text_json_for_rpc(custody_wlt_rpc, "make_integrated_address", req, resp);
|
||||
CHECK_AND_ASSERT_MES(r, "", "failed to call");
|
||||
return resp.payment_id;
|
||||
}
|
||||
|
||||
std::string get_integr_addr(tools::wallet_rpc_server& custody_wlt_rpc, const std::string payment_id)
|
||||
{
|
||||
pre_hf4_api::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::request req = AUTO_VAL_INIT(req);
|
||||
req.payment_id = payment_id;
|
||||
pre_hf4_api::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::response resp = AUTO_VAL_INIT(resp);
|
||||
bool r = invoke_text_json_for_rpc(custody_wlt_rpc, "make_integrated_address", req, resp);
|
||||
CHECK_AND_ASSERT_MES(r, "", "failed to call");
|
||||
return resp.integrated_address;
|
||||
}
|
||||
|
||||
#define TRANSFER_COMMENT "SSDVSf"
|
||||
std::string transfer_(std::shared_ptr<tools::wallet2> wlt, const std::string& address, uint64_t amount)
|
||||
{
|
||||
tools::wallet_rpc_server custody_wlt_rpc(wlt);
|
||||
pre_hf4_api::COMMAND_RPC_TRANSFER::request tr_req = AUTO_VAL_INIT(tr_req);
|
||||
tr_req.comment = TRANSFER_COMMENT;
|
||||
tr_req.destinations.resize(1);
|
||||
tr_req.destinations.back().address = address;
|
||||
tr_req.destinations.back().amount = amount;
|
||||
tr_req.fee = TX_DEFAULT_FEE;
|
||||
pre_hf4_api::COMMAND_RPC_TRANSFER::response tr_resp = AUTO_VAL_INIT(tr_resp);
|
||||
bool r = invoke_text_json_for_rpc(custody_wlt_rpc, "transfer", tr_req, tr_resp);
|
||||
CHECK_AND_ASSERT_MES(r, "", "failed to call");
|
||||
return tr_resp.tx_hash;
|
||||
}
|
||||
|
||||
bool test_payment_ids_generation(tools::wallet_rpc_server& custody_wlt_rpc)
|
||||
{
|
||||
//check make_integrated_address/split_integrated_address
|
||||
//check auto generated payment_id
|
||||
pre_hf4_api::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::request req = AUTO_VAL_INIT(req);
|
||||
pre_hf4_api::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::response resp = AUTO_VAL_INIT(resp);
|
||||
bool r = invoke_text_json_for_rpc(custody_wlt_rpc, "make_integrated_address", req, resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
//custody_wlt_rpc.handle_http_request()
|
||||
|
||||
pre_hf4_api::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS::request req2 = AUTO_VAL_INIT(req2);
|
||||
req2.integrated_address = resp.integrated_address;
|
||||
pre_hf4_api::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS::response resp2 = AUTO_VAL_INIT(resp2);
|
||||
r = invoke_text_json_for_rpc(custody_wlt_rpc, "split_integrated_address", req2, resp2);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
|
||||
CHECK_AND_ASSERT_MES(resp2.payment_id == resp.payment_id, false, "generated paymentids missmatched");
|
||||
|
||||
//check manually set payment_id
|
||||
req.payment_id = resp.payment_id;
|
||||
r = invoke_text_json_for_rpc(custody_wlt_rpc, "make_integrated_address", req, resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
//custody_wlt_rpc.handle_http_request()
|
||||
req2.integrated_address = resp.integrated_address;
|
||||
r = invoke_text_json_for_rpc(custody_wlt_rpc, "split_integrated_address", req2, resp2);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
|
||||
CHECK_AND_ASSERT_MES(resp2.payment_id == req.payment_id, false, "generated paymentids missmatched");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wallet_rpc_exchange_suite::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
|
||||
bool r = false;
|
||||
account_base alice_acc, bob_acc, carol_acc, custody_acc;
|
||||
alice_acc.generate();
|
||||
bob_acc.generate();
|
||||
carol_acc.generate();
|
||||
custody_acc.generate();
|
||||
|
||||
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX);
|
||||
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, alice_acc);
|
||||
std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, bob_acc);
|
||||
std::shared_ptr<tools::wallet2> carol_wlt = init_playtime_test_wallet(events, c, carol_acc);
|
||||
std::shared_ptr<tools::wallet2> custody_wlt = init_playtime_test_wallet(events, c, custody_acc);
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(alice_wlt->get_account().get_public_address(), c, 3);
|
||||
r = mine_next_pow_blocks_in_playtime(bob_wlt->get_account().get_public_address(), c, 3);
|
||||
r = mine_next_pow_blocks_in_playtime(carol_wlt->get_account().get_public_address(), c, 3);
|
||||
//r = mine_next_pow_blocks_in_playtime(custody_wlt->get_account().get_public_address(), c, 3);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
|
||||
// wallet RPC server
|
||||
tools::wallet_rpc_server custody_wlt_rpc(custody_wlt);
|
||||
|
||||
r = test_payment_ids_generation(custody_wlt_rpc);
|
||||
CHECK_AND_ASSERT_MES(r, false, "test_payment_ids_generation() failed ");
|
||||
//======================================================================
|
||||
std::string alice_payment_id = gen_payment_id(custody_wlt_rpc);
|
||||
std::string bob_payment_id = gen_payment_id(custody_wlt_rpc);
|
||||
std::string carol_payment_id = gen_payment_id(custody_wlt_rpc);
|
||||
|
||||
// generate payment id's for each wallet and deposit
|
||||
custody_wlt->refresh();
|
||||
alice_wlt->refresh();
|
||||
bob_wlt->refresh();
|
||||
carol_wlt->refresh();
|
||||
|
||||
#define TRANSFER_AMOUNT COIN / 10
|
||||
|
||||
std::string alice_tx1 = transfer_(alice_wlt, get_integr_addr(custody_wlt_rpc, alice_payment_id), TRANSFER_AMOUNT);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 1);
|
||||
|
||||
std::string bob_tx1 = transfer_(bob_wlt, get_integr_addr(custody_wlt_rpc, bob_payment_id), TRANSFER_AMOUNT);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 1);
|
||||
|
||||
std::string bob_tx2 = transfer_(bob_wlt, get_integr_addr(custody_wlt_rpc, bob_payment_id), TRANSFER_AMOUNT);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 1);
|
||||
|
||||
std::string carol_tx1 = transfer_(carol_wlt, get_integr_addr(custody_wlt_rpc, carol_payment_id), TRANSFER_AMOUNT);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 1);
|
||||
|
||||
std::string carol_tx2 = transfer_(carol_wlt, get_integr_addr(custody_wlt_rpc, carol_payment_id), TRANSFER_AMOUNT);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 1);
|
||||
|
||||
std::string carol_tx3 = transfer_(carol_wlt, get_integr_addr(custody_wlt_rpc, carol_payment_id), TRANSFER_AMOUNT);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 1);
|
||||
|
||||
CHECK_AND_ASSERT_MES(alice_tx1.size()
|
||||
&& bob_tx1.size()
|
||||
&& bob_tx2.size()
|
||||
&& carol_tx1.size()
|
||||
&& carol_tx2.size()
|
||||
&& carol_tx3.size(),
|
||||
false, "One of deposit transactions wan't created"
|
||||
);
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
custody_wlt->refresh();
|
||||
pre_hf4_api::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::request req = AUTO_VAL_INIT(req);
|
||||
req.update_provision_info = true;
|
||||
req.count = 10;
|
||||
|
||||
pre_hf4_api::COMMAND_RPC_GET_RECENT_TXS_AND_INFO::response resp = AUTO_VAL_INIT(resp);
|
||||
r = invoke_text_json_for_rpc(custody_wlt_rpc, "get_recent_txs_and_info", req, resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
|
||||
#define CHECK_RESPONSE_EQUAL(condition) CHECK_AND_ASSERT_MES((condition), false, "Failed check");
|
||||
|
||||
CHECK_RESPONSE_EQUAL(resp.pi.balance == 600000000000);
|
||||
CHECK_RESPONSE_EQUAL(resp.pi.unlocked_balance == 600000000000);
|
||||
CHECK_RESPONSE_EQUAL(resp.pi.transfers_count == 6);
|
||||
CHECK_RESPONSE_EQUAL(resp.total_transfers == 6);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers.size() == 6);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[0].comment == TRANSFER_COMMENT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[0].amount == TRANSFER_AMOUNT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[0].is_income == true);
|
||||
CHECK_RESPONSE_EQUAL(epee::string_tools::buff_to_hex_nodelimer(resp.transfers[0].payment_id) == carol_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(boost::lexical_cast<std::string>(resp.transfers[0].tx_hash) == carol_tx3);
|
||||
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[1].comment == TRANSFER_COMMENT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[1].amount == TRANSFER_AMOUNT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[1].is_income == true);
|
||||
CHECK_RESPONSE_EQUAL(epee::string_tools::buff_to_hex_nodelimer(resp.transfers[1].payment_id) == carol_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(boost::lexical_cast<std::string>(resp.transfers[1].tx_hash) == carol_tx2);
|
||||
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[2].comment == TRANSFER_COMMENT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[2].amount == TRANSFER_AMOUNT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[2].is_income == true);
|
||||
CHECK_RESPONSE_EQUAL(epee::string_tools::buff_to_hex_nodelimer(resp.transfers[2].payment_id) == carol_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(boost::lexical_cast<std::string>(resp.transfers[2].tx_hash) == carol_tx1);
|
||||
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[3].comment == TRANSFER_COMMENT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[3].amount == TRANSFER_AMOUNT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[3].is_income == true);
|
||||
CHECK_RESPONSE_EQUAL(epee::string_tools::buff_to_hex_nodelimer(resp.transfers[3].payment_id) == bob_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(boost::lexical_cast<std::string>(resp.transfers[3].tx_hash) == bob_tx2);
|
||||
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[4].comment == TRANSFER_COMMENT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[4].amount == TRANSFER_AMOUNT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[4].is_income == true);
|
||||
CHECK_RESPONSE_EQUAL(epee::string_tools::buff_to_hex_nodelimer(resp.transfers[4].payment_id) == bob_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(boost::lexical_cast<std::string>(resp.transfers[4].tx_hash) == bob_tx1);
|
||||
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[5].comment == TRANSFER_COMMENT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[5].amount == TRANSFER_AMOUNT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[5].is_income == true);
|
||||
CHECK_RESPONSE_EQUAL(epee::string_tools::buff_to_hex_nodelimer(resp.transfers[5].payment_id) == alice_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(boost::lexical_cast<std::string>(resp.transfers[5].tx_hash) == alice_tx1);
|
||||
|
||||
|
||||
req.count = 10;
|
||||
req.offset = 2;
|
||||
r = invoke_text_json_for_rpc(custody_wlt_rpc, "get_recent_txs_and_info", req, resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
|
||||
CHECK_RESPONSE_EQUAL(resp.pi.balance == 600000000000);
|
||||
CHECK_RESPONSE_EQUAL(resp.pi.unlocked_balance == 600000000000);
|
||||
CHECK_RESPONSE_EQUAL(resp.pi.transfers_count == 6);
|
||||
CHECK_RESPONSE_EQUAL(resp.total_transfers == 6);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers.size() == 4);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[0].comment == TRANSFER_COMMENT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[0].amount == TRANSFER_AMOUNT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[0].is_income == true);
|
||||
CHECK_RESPONSE_EQUAL(epee::string_tools::buff_to_hex_nodelimer(resp.transfers[0].payment_id) == carol_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(boost::lexical_cast<std::string>(resp.transfers[0].tx_hash) == carol_tx1);
|
||||
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[1].comment == TRANSFER_COMMENT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[1].amount == TRANSFER_AMOUNT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[1].is_income == true);
|
||||
CHECK_RESPONSE_EQUAL(epee::string_tools::buff_to_hex_nodelimer(resp.transfers[1].payment_id) == bob_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(boost::lexical_cast<std::string>(resp.transfers[1].tx_hash) == bob_tx2);
|
||||
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[2].comment == TRANSFER_COMMENT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[2].amount == TRANSFER_AMOUNT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[2].is_income == true);
|
||||
CHECK_RESPONSE_EQUAL(epee::string_tools::buff_to_hex_nodelimer(resp.transfers[2].payment_id) == bob_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(boost::lexical_cast<std::string>(resp.transfers[2].tx_hash) == bob_tx1);
|
||||
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[3].comment == TRANSFER_COMMENT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[3].amount == TRANSFER_AMOUNT);
|
||||
CHECK_RESPONSE_EQUAL(resp.transfers[3].is_income == true);
|
||||
CHECK_RESPONSE_EQUAL(epee::string_tools::buff_to_hex_nodelimer(resp.transfers[3].payment_id) == alice_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(boost::lexical_cast<std::string>(resp.transfers[3].tx_hash) == alice_tx1);
|
||||
|
||||
//getbalance
|
||||
pre_hf4_api::COMMAND_RPC_GET_BALANCE::request gb_req = AUTO_VAL_INIT(gb_req);
|
||||
pre_hf4_api::COMMAND_RPC_GET_BALANCE::response gb_resp = AUTO_VAL_INIT(gb_resp);
|
||||
r = invoke_text_json_for_rpc(custody_wlt_rpc, "getbalance", gb_req, gb_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
CHECK_RESPONSE_EQUAL(gb_resp.balance == 600000000000);
|
||||
CHECK_RESPONSE_EQUAL(gb_resp.unlocked_balance == 600000000000);
|
||||
|
||||
//get_wallet_info
|
||||
pre_hf4_api::COMMAND_RPC_GET_WALLET_INFO::request gwi_req = AUTO_VAL_INIT(gwi_req);
|
||||
pre_hf4_api::COMMAND_RPC_GET_WALLET_INFO::response gwi_resp = AUTO_VAL_INIT(gwi_resp);
|
||||
r = invoke_text_json_for_rpc(custody_wlt_rpc, "get_wallet_info", gwi_req, gwi_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
CHECK_RESPONSE_EQUAL(gwi_resp.current_height == 35);
|
||||
CHECK_RESPONSE_EQUAL(gwi_resp.transfer_entries_count == 6);
|
||||
CHECK_RESPONSE_EQUAL(gwi_resp.transfers_count == 6);
|
||||
CHECK_RESPONSE_EQUAL(gwi_resp.address == custody_wlt->get_account().get_public_address_str());
|
||||
|
||||
|
||||
//search_for_transactions
|
||||
pre_hf4_api::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::request st_req = AUTO_VAL_INIT(st_req);
|
||||
st_req.filter_by_height = false;
|
||||
st_req.in = true;
|
||||
st_req.out = true;
|
||||
st_req.pool = true;
|
||||
st_req.tx_id = resp.transfers[1].tx_hash; //bob_tx2
|
||||
pre_hf4_api::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::response st_resp = AUTO_VAL_INIT(st_resp);
|
||||
r = invoke_text_json_for_rpc(custody_wlt_rpc, "search_for_transactions", st_req, st_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
//TODO: add more cases for search transaction in pool, in and out
|
||||
|
||||
|
||||
CHECK_RESPONSE_EQUAL(st_resp.in.size() == 1);
|
||||
CHECK_RESPONSE_EQUAL(st_resp.in.begin()->comment == TRANSFER_COMMENT);
|
||||
CHECK_RESPONSE_EQUAL(st_resp.in.begin()->amount == TRANSFER_AMOUNT);
|
||||
CHECK_RESPONSE_EQUAL(st_resp.in.begin()->is_income == true);
|
||||
CHECK_RESPONSE_EQUAL(epee::string_tools::buff_to_hex_nodelimer(st_resp.in.begin()->payment_id) == bob_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(boost::lexical_cast<std::string>(st_resp.in.begin()->tx_hash) == bob_tx2);
|
||||
|
||||
|
||||
//get_payments
|
||||
pre_hf4_api::COMMAND_RPC_GET_PAYMENTS::request gps_req = AUTO_VAL_INIT(gps_req);
|
||||
gps_req.payment_id = carol_payment_id;
|
||||
pre_hf4_api::COMMAND_RPC_GET_PAYMENTS::response gps_resp = AUTO_VAL_INIT(gps_resp);
|
||||
r = invoke_text_json_for_rpc(custody_wlt_rpc, "get_payments", gps_req, gps_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
|
||||
{
|
||||
//sort by block_height to have deterministic order
|
||||
gps_resp.payments.sort([&](const pre_hf4_api::payment_details& a, const pre_hf4_api::payment_details& b) {return a.block_height < b.block_height; });
|
||||
|
||||
CHECK_RESPONSE_EQUAL(gps_resp.payments.size() == 3);
|
||||
auto it = gps_resp.payments.begin();
|
||||
CHECK_RESPONSE_EQUAL(it->amount == 100000000000);
|
||||
CHECK_RESPONSE_EQUAL(it->payment_id == carol_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(it->block_height == 23);
|
||||
it++;
|
||||
CHECK_RESPONSE_EQUAL(it->amount == 100000000000);
|
||||
CHECK_RESPONSE_EQUAL(it->payment_id == carol_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(it->block_height == 24);
|
||||
it++;
|
||||
CHECK_RESPONSE_EQUAL(it->amount == 100000000000);
|
||||
CHECK_RESPONSE_EQUAL(it->payment_id == carol_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(it->block_height == 25);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//get_bulk_payments
|
||||
pre_hf4_api::COMMAND_RPC_GET_BULK_PAYMENTS::request gbps_req = AUTO_VAL_INIT(gbps_req);
|
||||
gbps_req.payment_ids.push_back(bob_payment_id);
|
||||
gbps_req.payment_ids.push_back(alice_payment_id);
|
||||
pre_hf4_api::COMMAND_RPC_GET_BULK_PAYMENTS::response gbps_resp = AUTO_VAL_INIT(gbps_resp);
|
||||
r = invoke_text_json_for_rpc(custody_wlt_rpc, "get_bulk_payments", gbps_req, gbps_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
|
||||
{
|
||||
//sort by block_height to have deterministic order
|
||||
gbps_resp.payments.sort([&](const pre_hf4_api::payment_details& a, const pre_hf4_api::payment_details& b) {return a.block_height < b.block_height; });
|
||||
|
||||
CHECK_RESPONSE_EQUAL(gbps_resp.payments.size() == 3);
|
||||
auto it = gbps_resp.payments.begin();
|
||||
CHECK_RESPONSE_EQUAL(it->amount == 100000000000);
|
||||
CHECK_RESPONSE_EQUAL(it->payment_id == alice_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(it->block_height == 20);
|
||||
it++;
|
||||
CHECK_RESPONSE_EQUAL(it->amount == 100000000000);
|
||||
CHECK_RESPONSE_EQUAL(it->payment_id == bob_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(it->block_height == 21);
|
||||
it++;
|
||||
CHECK_RESPONSE_EQUAL(it->amount == 100000000000);
|
||||
CHECK_RESPONSE_EQUAL(it->payment_id == bob_payment_id);
|
||||
CHECK_RESPONSE_EQUAL(it->block_height == 22);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,3 +28,16 @@ struct wallet_rpc_transfer : public wallet_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);
|
||||
};
|
||||
|
||||
/*
|
||||
Tests to make sure api for exchanges didn't change after HF4(Zarcanum)
|
||||
testing api: get_recent_txs_and_info, make_integrated_address,
|
||||
getbalance, get_wallet_info, get_transfer_by_txid,
|
||||
*/
|
||||
struct wallet_rpc_exchange_suite : public wallet_test
|
||||
{
|
||||
wallet_rpc_exchange_suite();
|
||||
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);
|
||||
};
|
||||
|
||||
|
|
|
|||
431
tests/core_tests/wallet_rpc_tests_legacy_defs.h
Normal file
431
tests/core_tests/wallet_rpc_tests_legacy_defs.h
Normal file
|
|
@ -0,0 +1,431 @@
|
|||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace pre_hf4_api
|
||||
{
|
||||
struct COMMAND_RPC_MAKE_INTEGRATED_ADDRESS
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string payment_id; // hex-encoded
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(payment_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string integrated_address;
|
||||
std::string payment_id; // hex-encoded
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(integrated_address)
|
||||
KV_SERIALIZE(payment_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string integrated_address;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(integrated_address)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string standard_address;
|
||||
std::string payment_id; // hex-encoded
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(standard_address)
|
||||
KV_SERIALIZE(payment_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct transfer_destination
|
||||
{
|
||||
uint64_t amount;
|
||||
std::string address;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amount)
|
||||
KV_SERIALIZE(address)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct tx_service_attachment
|
||||
{
|
||||
std::string service_id; //string identifying service which addressed this attachment
|
||||
std::string instruction; //string identifying specific instructions for service/way to interpret data
|
||||
std::string body; //any data identifying service, options etc
|
||||
std::vector<crypto::public_key> security; //some of commands need proof of owner
|
||||
uint8_t flags; //special flags (ex: TX_SERVICE_ATTACHMENT_ENCRYPT_BODY), see below
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(service_id)
|
||||
FIELD(instruction)
|
||||
FIELD(body)
|
||||
FIELD(security)
|
||||
FIELD(flags)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(service_id)
|
||||
KV_SERIALIZE(instruction)
|
||||
KV_SERIALIZE_BLOB_AS_HEX_STRING(body)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(security)
|
||||
KV_SERIALIZE(flags)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_TRANSFER
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::list<transfer_destination> destinations;
|
||||
uint64_t fee;
|
||||
uint64_t mixin;
|
||||
//uint64_t unlock_time;
|
||||
std::string payment_id; // hex-encoded
|
||||
std::string comment;
|
||||
bool push_payer;
|
||||
bool hide_receiver;
|
||||
std::vector<currency::tx_service_attachment> service_entries;
|
||||
bool service_entries_permanent;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(destinations)
|
||||
KV_SERIALIZE(fee)
|
||||
KV_SERIALIZE(mixin)
|
||||
KV_SERIALIZE(payment_id)
|
||||
KV_SERIALIZE(comment)
|
||||
KV_SERIALIZE(push_payer)
|
||||
KV_SERIALIZE(hide_receiver)
|
||||
KV_SERIALIZE(service_entries)
|
||||
KV_SERIALIZE(service_entries_permanent)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string tx_hash;
|
||||
std::string tx_unsigned_hex; // for cold-signing process
|
||||
uint64_t tx_size;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(tx_hash)
|
||||
KV_SERIALIZE(tx_unsigned_hex)
|
||||
KV_SERIALIZE(tx_size)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct wallet_transfer_info_details
|
||||
{
|
||||
std::list<uint64_t> rcv;
|
||||
std::list<uint64_t> spn;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(rcv)
|
||||
KV_SERIALIZE(spn)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
};
|
||||
|
||||
struct wallet_transfer_info
|
||||
{
|
||||
uint64_t amount;
|
||||
uint64_t timestamp;
|
||||
crypto::hash tx_hash;
|
||||
uint64_t height; //if height == 0 then tx is unconfirmed
|
||||
uint64_t unlock_time;
|
||||
uint32_t tx_blob_size;
|
||||
std::string payment_id;
|
||||
std::vector<std::string> remote_addresses; //optional
|
||||
std::vector<std::string> recipients_aliases; //optional
|
||||
std::string comment;
|
||||
bool is_income;
|
||||
bool is_service;
|
||||
bool is_mixing;
|
||||
bool is_mining;
|
||||
uint64_t tx_type;
|
||||
wallet_transfer_info_details td;
|
||||
std::vector<tx_service_attachment> service_entries;
|
||||
//not included in streaming serialization
|
||||
uint64_t fee;
|
||||
bool show_sender;
|
||||
//std::vector<escrow_contract_details> contract; //not traxking this part
|
||||
uint16_t extra_flags;
|
||||
uint64_t transfer_internal_index;
|
||||
|
||||
|
||||
//not included in kv serialization map
|
||||
currency::transaction tx;
|
||||
std::vector<uint64_t> selected_indicies;
|
||||
std::list<bc_services::offers_attachment_t> marketplace_entries;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amount)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(tx_hash)
|
||||
KV_SERIALIZE(height)
|
||||
KV_SERIALIZE(unlock_time)
|
||||
KV_SERIALIZE(tx_blob_size)
|
||||
KV_SERIALIZE_BLOB_AS_HEX_STRING(payment_id)
|
||||
KV_SERIALIZE(remote_addresses)
|
||||
KV_SERIALIZE(recipients_aliases)
|
||||
KV_SERIALIZE(comment)
|
||||
KV_SERIALIZE(is_income)
|
||||
KV_SERIALIZE(timestamp)
|
||||
KV_SERIALIZE(td)
|
||||
KV_SERIALIZE(fee)
|
||||
KV_SERIALIZE(is_service)
|
||||
KV_SERIALIZE(is_mixing)
|
||||
KV_SERIALIZE(is_mining)
|
||||
KV_SERIALIZE(tx_type)
|
||||
KV_SERIALIZE(show_sender)
|
||||
//KV_SERIALIZE(contract)
|
||||
KV_SERIALIZE(service_entries)
|
||||
KV_SERIALIZE(transfer_internal_index)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct wallet_provision_info
|
||||
{
|
||||
uint64_t transfers_count;
|
||||
uint64_t transfer_entries_count;
|
||||
uint64_t balance;
|
||||
uint64_t unlocked_balance;
|
||||
uint64_t curent_height;
|
||||
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(transfers_count)
|
||||
KV_SERIALIZE(transfer_entries_count)
|
||||
KV_SERIALIZE(balance)
|
||||
KV_SERIALIZE(unlocked_balance)
|
||||
KV_SERIALIZE(curent_height)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_GET_RECENT_TXS_AND_INFO
|
||||
{
|
||||
struct request
|
||||
{
|
||||
|
||||
/*
|
||||
if offset is 0, then GET_RECENT_TXS_AND_INFO return
|
||||
unconfirmed transactions as the first first items of "transfers",
|
||||
this unconfirmed transactions is not counted regarding "count" parameter
|
||||
*/
|
||||
uint64_t offset;
|
||||
uint64_t count;
|
||||
|
||||
/*
|
||||
need_to_get_info - should backend re-calculate balance(could be relatively heavy,
|
||||
and not needed when getting long tx history with multiple calls
|
||||
of GET_RECENT_TXS_AND_INFO with offsets)
|
||||
*/
|
||||
bool update_provision_info;
|
||||
bool exclude_mining_txs;
|
||||
bool exclude_unconfirmed;
|
||||
std::string order; // "FROM_BEGIN_TO_END" or "FROM_END_TO_BEGIN"
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(offset)
|
||||
KV_SERIALIZE(count)
|
||||
KV_SERIALIZE(update_provision_info)
|
||||
KV_SERIALIZE(exclude_mining_txs)
|
||||
KV_SERIALIZE(exclude_unconfirmed)
|
||||
KV_SERIALIZE(order)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
wallet_provision_info pi;
|
||||
std::vector<wallet_transfer_info> transfers;
|
||||
uint64_t total_transfers;
|
||||
uint64_t last_item_index;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(pi)
|
||||
KV_SERIALIZE(transfers)
|
||||
KV_SERIALIZE(total_transfers)
|
||||
KV_SERIALIZE(last_item_index)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct COMMAND_RPC_GET_BALANCE
|
||||
{
|
||||
struct request
|
||||
{
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
uint64_t balance;
|
||||
uint64_t unlocked_balance;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(balance)
|
||||
KV_SERIALIZE(unlocked_balance)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct COMMAND_RPC_GET_WALLET_INFO
|
||||
{
|
||||
struct request
|
||||
{
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string address;
|
||||
std::string path;
|
||||
uint64_t transfers_count;
|
||||
uint64_t transfer_entries_count;
|
||||
bool is_whatch_only;
|
||||
std::vector<std::string> utxo_distribution;
|
||||
uint64_t current_height;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(address)
|
||||
KV_SERIALIZE(path)
|
||||
KV_SERIALIZE(transfers_count)
|
||||
KV_SERIALIZE(transfer_entries_count)
|
||||
KV_SERIALIZE(is_whatch_only)
|
||||
KV_SERIALIZE(utxo_distribution)
|
||||
KV_SERIALIZE(current_height)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct COMMAND_RPC_SEARCH_FOR_TRANSACTIONS
|
||||
{
|
||||
struct request
|
||||
{
|
||||
crypto::hash tx_id;
|
||||
bool in;
|
||||
bool out;
|
||||
//bool pending;
|
||||
//bool failed;
|
||||
bool pool;
|
||||
bool filter_by_height;
|
||||
uint64_t min_height;
|
||||
uint64_t max_height;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(tx_id)
|
||||
KV_SERIALIZE(in)
|
||||
KV_SERIALIZE(out)
|
||||
//KV_SERIALIZE(pending)
|
||||
//KV_SERIALIZE(failed)
|
||||
KV_SERIALIZE(pool)
|
||||
KV_SERIALIZE(filter_by_height)
|
||||
KV_SERIALIZE(min_height)
|
||||
KV_SERIALIZE(max_height)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::list<wallet_transfer_info> in;
|
||||
std::list<wallet_transfer_info> out;
|
||||
//std::list<wallet_transfer_info> pending;
|
||||
//std::list<wallet_transfer_info> failed;
|
||||
std::list<wallet_transfer_info> pool;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(in)
|
||||
KV_SERIALIZE(out)
|
||||
//KV_SERIALIZE(pending)
|
||||
//KV_SERIALIZE(failed)
|
||||
KV_SERIALIZE(pool)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct payment_details
|
||||
{
|
||||
std::string payment_id;
|
||||
std::string tx_hash;
|
||||
uint64_t amount;
|
||||
uint64_t block_height;
|
||||
uint64_t unlock_time;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(payment_id)
|
||||
KV_SERIALIZE(tx_hash)
|
||||
KV_SERIALIZE(amount)
|
||||
KV_SERIALIZE(block_height)
|
||||
KV_SERIALIZE(unlock_time)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_GET_PAYMENTS
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string payment_id; // hex-encoded
|
||||
bool allow_locked_transactions;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(payment_id)
|
||||
KV_SERIALIZE(allow_locked_transactions)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::list<payment_details> payments;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(payments)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_GET_BULK_PAYMENTS
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::vector<std::string> payment_ids;
|
||||
uint64_t min_block_height;
|
||||
bool allow_locked_transactions;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(payment_ids)
|
||||
KV_SERIALIZE(min_block_height)
|
||||
KV_SERIALIZE(allow_locked_transactions)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::list<payment_details> payments;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(payments)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -65,6 +65,7 @@ bool create_block_template_manually(const currency::block& prev_block, boost::mu
|
|||
// make things really simple by assuming block size is less than CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE
|
||||
size_t median_size = 0;
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
uint64_t block_reward = 0;
|
||||
|
||||
bool r = construct_miner_tx(get_block_height(prev_block) + 1,
|
||||
median_size,
|
||||
|
|
@ -75,6 +76,7 @@ bool create_block_template_manually(const currency::block& prev_block, boost::mu
|
|||
miner_addr,
|
||||
result.miner_tx,
|
||||
block_reward_without_fee,
|
||||
block_reward,
|
||||
TRANSACTION_VERSION_PRE_HF4);
|
||||
CHECK_AND_ASSERT_MES(r, false, "construct_miner_tx failed");
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,9 @@ TEST(parse_and_validate_tx_extra, is_correct_parse_and_validate_tx_extra)
|
|||
currency::account_base acc;
|
||||
acc.generate();
|
||||
currency::blobdata b = "dsdsdfsdfsf";
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
bool r = currency::construct_miner_tx(0, 0, 10000000000000, 1000, TESTS_DEFAULT_FEE, acc.get_keys().account_address, acc.get_keys().account_address, tx, block_reward_without_fee, TRANSACTION_VERSION_PRE_HF4, b, 1);
|
||||
uint64_t block_reward_without_fee = 0, block_reward = 0;
|
||||
bool r = currency::construct_miner_tx(0, 0, 10000000000000, 1000, TESTS_DEFAULT_FEE, acc.get_keys().account_address, acc.get_keys().account_address, tx,
|
||||
block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, b, 1);
|
||||
ASSERT_TRUE(r);
|
||||
crypto::public_key tx_pub_key;
|
||||
r = currency::parse_and_validate_tx_extra(tx, tx_pub_key);
|
||||
|
|
@ -27,8 +28,9 @@ TEST(parse_and_validate_tx_extra, is_correct_extranonce_too_big)
|
|||
currency::account_base acc;
|
||||
acc.generate();
|
||||
currency::blobdata b(260, 0);
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
bool r = currency::construct_miner_tx(0, 0, 10000000000000, 1000, TESTS_DEFAULT_FEE, acc.get_keys().account_address, acc.get_keys().account_address, tx, block_reward_without_fee, TRANSACTION_VERSION_PRE_HF4, b, 1);
|
||||
uint64_t block_reward_without_fee = 0, block_reward = 0;
|
||||
bool r = currency::construct_miner_tx(0, 0, 10000000000000, 1000, TESTS_DEFAULT_FEE, acc.get_keys().account_address, acc.get_keys().account_address, tx,
|
||||
block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, b, 1);
|
||||
ASSERT_FALSE(r);
|
||||
}
|
||||
|
||||
|
|
@ -56,7 +58,7 @@ TEST(parse_and_validate_tx_extra, test_payment_ids)
|
|||
ASSERT_TRUE(r);
|
||||
|
||||
std::string h2;
|
||||
r = currency::get_payment_id_from_tx(tx.attachment, h2);
|
||||
r = currency::get_payment_id_from_decrypted_container(tx.attachment, h2);
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(h, h2);
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ echo "Building...."
|
|||
|
||||
rm -rf build; mkdir -p build/release;
|
||||
cd build/release;
|
||||
cmake $testnet_def -D STATIC=true -D ARCH=x86-64 -D BUILD_GUI=TRUE -D OPENSSL_ROOT_DIR="$OPENSSL_ROOT_DIR" -D CMAKE_PREFIX_PATH="$QT_PREFIX_PATH" -D CMAKE_BUILD_TYPE=Release ../..
|
||||
cmake $testnet_def -D STATIC=true -D ARCH=x86-64 -D DISABLE_TOR=TRUE -D BUILD_GUI=TRUE -D OPENSSL_ROOT_DIR="$OPENSSL_ROOT_DIR" -D CMAKE_PREFIX_PATH="$QT_PREFIX_PATH" -D CMAKE_BUILD_TYPE=Release ../..
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to run cmake"
|
||||
exit 1
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue