forked from lthn/blockchain
Merge branch 'develop' into release
This commit is contained in:
commit
6ff59ca8cd
45 changed files with 1075 additions and 230 deletions
|
|
@ -13,6 +13,9 @@ set(VERSION "1.0")
|
|||
# cmake_policy(SET CMP0020 OLD)
|
||||
# endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
add_definitions(-DMOBILE_WALLET_BUILD)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "iOS" )
|
||||
|
|
@ -52,7 +55,7 @@ enable_testing()
|
|||
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.10.5)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.10.5 CACHE STRING "Minimum OS X deployment version")
|
||||
endif()
|
||||
|
||||
set(USE_PCH FALSE CACHE BOOL "Use shared precompiled headers")
|
||||
|
|
@ -182,6 +185,11 @@ else()
|
|||
endif()
|
||||
|
||||
|
||||
# If BOOST_ROOT is set, ignore system-wide Boost
|
||||
if(DEFINED ENV{BOOST_ROOT})
|
||||
set(Boost_NO_SYSTEM_PATHS ON)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
endif()
|
||||
|
|
|
|||
33
README.md
33
README.md
|
|
@ -13,13 +13,13 @@ Be sure to clone the repository properly:\
|
|||
### Dependencies
|
||||
| component / version | minimum <br>(not recommended but may work) | recommended | most recent of what we have ever tested |
|
||||
|--|--|--|--|
|
||||
| gcc (Linux) | 5.4.0 | 7.5.0 | 8.3.0 |
|
||||
| gcc (Linux) | 5.4.0 | 9.4.0 | 12.3.0 |
|
||||
| llvm/clang (Linux) | UNKNOWN | 7.0.1 | 8.0.0 |
|
||||
| [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2015 (14.0 update 1) | 2017 (15.9.0) | 2022 (17.4.2) |
|
||||
| [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2015 (14.0 update 1) | 2017 (15.9.0) | 2022 (17.7.5) |
|
||||
| [XCode](https://developer.apple.com/downloads/) (macOS) | 9.2 | 12.3 | 12.3 |
|
||||
| [CMake](https://cmake.org/download/) | 2.8.6 | 3.15.5 | 3.26.3 |
|
||||
| [CMake](https://cmake.org/download/) | 3.15.5 | 3.22.1 | 3.26.3 |
|
||||
| [Boost](https://www.boost.org/users/download/) | 1.70 | 1.70 | 1.76 |
|
||||
| [OpenSSL](https://www.openssl.org/source/) [(win)](https://slproweb.com/products/Win32OpenSSL.html) | - | 1.1.1n | 1.1.1n |
|
||||
| [OpenSSL](https://www.openssl.org/source/) [(win)](https://slproweb.com/products/Win32OpenSSL.html) | 1.1.1n | 1.1.1w | 1.1.1w |
|
||||
| [Qt](https://download.qt.io/archive/qt/) (*only for GUI*) | 5.8.0 | 5.11.2 | 5.15.2 |
|
||||
|
||||
Note:\
|
||||
|
|
@ -30,25 +30,28 @@ Note:\
|
|||
|
||||
### Linux
|
||||
|
||||
Recommended OS version: Ubuntu 18.04 LTS.
|
||||
Recommended OS versions: Ubuntu 20.04, 22.04 LTS.
|
||||
|
||||
1. Prerequisites
|
||||
|
||||
[*server version*]
|
||||
|
||||
sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen checkinstall zlib1g-dev
|
||||
sudo apt-get install -y build-essential g++ curl autotools-dev libicu-dev libbz2-dev cmake git screen checkinstall zlib1g-dev
|
||||
|
||||
[*GUI version*]
|
||||
|
||||
sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git screen checkinstall zlib1g-dev mesa-common-dev libglu1-mesa-dev
|
||||
|
||||
2. Download and build Boost
|
||||
2. Download and build Boost\
|
||||
(Assuming you have cloned Zano into the 'zano' folder. If you used a different location for Zano, edit line 4 accordingly.)
|
||||
|
||||
curl -OL https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.bz2
|
||||
echo "430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 boost_1_70_0.tar.bz2" | shasum -c && tar -xjf boost_1_70_0.tar.bz2
|
||||
cd boost_1_70_0
|
||||
rm boost_1_70_0.tar.bz2 && cd boost_1_70_0
|
||||
patch -p0 < ../zano/utils/boost_1.70_gcc_8.patch || cd ..
|
||||
./bootstrap.sh --with-libraries=system,filesystem,thread,date_time,chrono,regex,serialization,atomic,program_options,locale,timer,log
|
||||
./b2
|
||||
Make sure that you see "The Boost C++ Libraries were successfully built!" message at the end.
|
||||
|
||||
3. Install Qt\
|
||||
(*GUI version only, skip this step if you're building server version*)
|
||||
|
|
@ -63,15 +66,13 @@ Recommended OS version: Ubuntu 18.04 LTS.
|
|||
|
||||
4. Install OpenSSL
|
||||
|
||||
We recommend installing OpenSSL v1.1.1n locally unless you would like to use the same version system-wide. Adjust the local path `/home/user/openssl` in the commands below according to your needs.
|
||||
We recommend installing OpenSSL v1.1.1w locally unless you would like to use the same version system-wide. Adjust the local path `/home/user/openssl` in the commands below according to your needs.
|
||||
|
||||
curl -OL https://www.openssl.org/source/openssl-1.1.1n.tar.gz
|
||||
echo "40dceb51a4f6a5275bde0e6bf20ef4b91bfc32ed57c0552e2e8e15463372b17a openssl-1.1.1n.tar.gz" | shasum -c && tar xaf openssl-1.1.1n.tar.gz
|
||||
cd openssl-1.1.1n/
|
||||
curl -OL https://www.openssl.org/source/openssl-1.1.1w.tar.gz
|
||||
echo "cf3098950cb4d853ad95c0841f1f9c6d3dc102dccfcacd521d93925208b76ac8 openssl-1.1.1w.tar.gz" | shasum -c && tar xaf openssl-1.1.1w.tar.gz
|
||||
cd openssl-1.1.1w/
|
||||
./config --prefix=/home/user/openssl --openssldir=/home/user/openssl shared zlib
|
||||
make
|
||||
make test
|
||||
make install
|
||||
make && make test && make install
|
||||
|
||||
|
||||
5. Set environment variables properly\
|
||||
|
|
@ -89,7 +90,7 @@ For instance, by adding the following lines to `~/.bashrc`
|
|||
export OPENSSL_ROOT_DIR=/home/user/openssl
|
||||
export QT_PREFIX_PATH=/home/user/Qt5.11.2/5.11.2/gcc_64
|
||||
|
||||
|
||||
Make sure you've restarted your terminal session (by reopening the terminal window or reconnecting the server) to apply these changes.
|
||||
|
||||
6. Build the binaries
|
||||
1. Build daemon and simplewallet:
|
||||
|
|
|
|||
|
|
@ -123,22 +123,22 @@ DISABLE_VS_WARNINGS(4100)
|
|||
|
||||
#if defined(ENABLE_LOGGING_INTERNAL)
|
||||
|
||||
#define LOG_PRINT_CHANNEL_NO_PREFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
#define LOG_PRINT_CHANNEL_NO_PREFIX2(log_channel, log_name, x, y) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
{TRY_ENTRY();std::stringstream ss________; ss________ << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str() , y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}}
|
||||
|
||||
#define LOG_PRINT_CHANNEL_NO_PREFIX_NO_POSTFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
#define LOG_PRINT_CHANNEL_NO_PREFIX_NO_POSTFIX2(log_channel, log_name, x, y) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
{TRY_ENTRY();std::stringstream ss________; ss________ << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}}
|
||||
|
||||
#define LOG_PRINT_CHANNEL_NO_POSTFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
#define LOG_PRINT_CHANNEL_NO_POSTFIX2(log_channel, log_name, x, y) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
{TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}}
|
||||
|
||||
#define LOG_PRINT_CHANNEL2_CB(log_channel, log_name, x, y, cb) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
#define LOG_PRINT_CHANNEL2_CB(log_channel, log_name, x, y, cb) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
{TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);cb(ss________.str());CATCH_ALL_DO_NOTHING();}}
|
||||
|
||||
#define LOG_PRINT_CHANNEL_COLOR2_CB(log_channel, log_name, x, y, color, cb) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
#define LOG_PRINT_CHANNEL_COLOR2_CB(log_channel, log_name, x, y, color, cb) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
{TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, color, false, log_name); cb(ss________.str());CATCH_ALL_DO_NOTHING();}}
|
||||
|
||||
#define LOG_PRINT_CHANNEL_2_JORNAL(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
#define LOG_PRINT_CHANNEL_2_JORNAL(log_channel, log_name, x, y) {if ( (y) <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\
|
||||
{TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, true, log_name);CATCH_ALL_DO_NOTHING();}}
|
||||
|
||||
#define LOG_ERROR2_CB(log_name, x, cb) { \
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ using namespace std;
|
|||
LOG_PRINT("Reconnecting...", LOG_LEVEL_3);
|
||||
if(!connect(m_host_buff, m_port))
|
||||
{
|
||||
LOG_PRINT("Failed to connect to " << m_host_buff << ":" << m_port, LOG_LEVEL_3);
|
||||
LOG_PRINT("Failed to connect to " << m_host_buff << ":" << m_port, LOG_LEVEL_1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -370,7 +370,7 @@ using namespace std;
|
|||
{
|
||||
if(!m_net_client.recv(recv_buffer))
|
||||
{
|
||||
LOG_PRINT("Unexpected reciec fail", LOG_LEVEL_3);
|
||||
LOG_PRINT("Unexpected reciec fail", LOG_LEVEL_2);
|
||||
m_state = reciev_machine_state_error;
|
||||
}
|
||||
if(!recv_buffer.size())
|
||||
|
|
@ -415,10 +415,10 @@ using namespace std;
|
|||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_PRINT_L3("Returning false because of wrong state machine. state: " << m_state);
|
||||
return false;
|
||||
}
|
||||
{
|
||||
LOG_PRINT_L3("Returning false because of wrong state machine. state: " << m_state);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
inline
|
||||
|
|
|
|||
|
|
@ -30,12 +30,20 @@
|
|||
#include "storages/portable_storage_template_helper.h"
|
||||
#include "http_base.h"
|
||||
|
||||
|
||||
|
||||
template<typename typename_t>
|
||||
typename_t get_documentation_json_struct()
|
||||
{
|
||||
return AUTO_VAL_INIT_T(typename_t);
|
||||
}
|
||||
|
||||
template<typename request_t, typename response_t>
|
||||
bool auto_doc_t(const std::string& prefix_name, std::string& generate_reference)
|
||||
{
|
||||
if (!generate_reference.size()) return true;
|
||||
request_t req = AUTO_VAL_INIT(req);
|
||||
response_t res = AUTO_VAL_INIT(res);
|
||||
request_t req = get_documentation_json_struct<request_t>();
|
||||
response_t res = get_documentation_json_struct<response_t>();
|
||||
std::stringstream ss;
|
||||
ss << prefix_name << ENDL
|
||||
<< "REQUEST: " << ENDL << epee::serialization::store_t_to_json(req) << ENDL << "--------------------------------" << ENDL
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ namespace epee
|
|||
bool res = m_net_server.init_server(bind_port, bind_ip);
|
||||
if(!res)
|
||||
{
|
||||
LOG_ERROR("Failed to bind server");
|
||||
LOG_ERROR("Failed to bind to " << bind_ip << ":" << bind_port);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -74,14 +74,14 @@ namespace epee
|
|||
bool run(size_t threads_count, bool wait = true)
|
||||
{
|
||||
//go to loop
|
||||
LOG_PRINT("Run net_service loop( " << threads_count << " threads)...", LOG_LEVEL_0);
|
||||
LOG_PRINT("Run net_service loop (" << threads_count << " threads)...", LOG_LEVEL_1);
|
||||
if(!m_net_server.run_server(threads_count, wait))
|
||||
{
|
||||
LOG_ERROR("Failed to run net tcp server!");
|
||||
}
|
||||
|
||||
if(wait)
|
||||
LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0);
|
||||
LOG_PRINT("net_service loop stopped.", LOG_LEVEL_1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ namespace epee
|
|||
t_pod_type transform_str_to_t_pod(const std::string& a)
|
||||
{
|
||||
t_pod_type res = AUTO_VAL_INIT(res);
|
||||
if (a.empty())
|
||||
return res;
|
||||
if (!epee::string_tools::hex_to_pod(a, res))
|
||||
throw std::runtime_error(std::string("Unable to transform \"") + a + "\" to pod type " + typeid(t_pod_type).name());
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -77,8 +77,7 @@ namespace epee
|
|||
bool insert_next_section(harray hSecArray, hsection& hinserted_childsection);
|
||||
//------------------------------------------------------------------------
|
||||
//delete entry (section, value or array)
|
||||
bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr);
|
||||
|
||||
bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr);
|
||||
//-------------------------------------------------------------------------------
|
||||
bool store_to_binary(binarybuffer& target);
|
||||
bool load_from_binary(const binarybuffer& target);
|
||||
|
|
@ -87,6 +86,8 @@ namespace epee
|
|||
bool dump_as_json(std::string& targetObj, size_t indent = 0, end_of_line_t eol = eol_crlf);
|
||||
bool load_from_json(const std::string& source);
|
||||
|
||||
template<typename cb_t>
|
||||
bool enum_entries(hsection hparent_section, cb_t cb);
|
||||
private:
|
||||
section m_root;
|
||||
hsection get_root_section() {return &m_root;}
|
||||
|
|
@ -384,6 +385,20 @@ namespace epee
|
|||
CATCH_ENTRY("portable_storage::insert_first_value", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<typename cb_t>
|
||||
bool portable_storage::enum_entries(hsection hparent_section, cb_t cb)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
if (!hparent_section) hparent_section = &m_root;
|
||||
for (const auto& e : hparent_section->m_entries)
|
||||
{
|
||||
if (!cb(e.first, e.second))
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::enum_entries", false);
|
||||
}
|
||||
|
||||
template<class t_value>
|
||||
bool portable_storage::insert_next_value(harray hval_array, const t_value& target)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <cctype>
|
||||
#include "warnings.h"
|
||||
|
||||
|
||||
|
|
@ -310,7 +311,14 @@ namespace string_encoding
|
|||
return get_md5_as_hexstring(src.data(), src.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
inline
|
||||
std::string toupper(std::string s)
|
||||
{
|
||||
std::transform(s.begin(), s.end(), s.begin(),
|
||||
[](unsigned char c) { return std::toupper(c); } // correct
|
||||
);
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2569,14 +2569,14 @@ bool blockchain_storage::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDO
|
|||
}
|
||||
if (result_outs.outs.size() < req.outs_count)
|
||||
{
|
||||
LOG_PRINT_RED_L0("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.outs_count << ", added " << result_outs.outs.size() << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total");
|
||||
LOG_PRINT_YELLOW("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.outs_count << ", added " << result_outs.outs.size() << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total", LOG_LEVEL_0);
|
||||
}
|
||||
}else
|
||||
{
|
||||
size_t added = 0;
|
||||
for (size_t i = 0; i != up_index_limit; i++)
|
||||
added += add_out_to_get_random_outs(result_outs, amount, i, req.outs_count, req.use_forced_mix_outs) ? 1 : 0;
|
||||
LOG_PRINT_RED_L0("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.outs_count << ", added " << added << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total - respond with all good outs");
|
||||
LOG_PRINT_YELLOW("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.outs_count << ", added " << added << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total - respond with all good outs", LOG_LEVEL_0);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -2808,6 +2808,51 @@ size_t blockchain_storage::get_current_sequence_factor_for_alt(alt_chain_type& a
|
|||
return n;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::get_pos_votes(uint64_t start_index, uint64_t end_index, vote_results& r)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
if (start_index >= m_db_blocks.size() || start_index >= end_index)
|
||||
{
|
||||
//LOG_PRINT_L0("Wrong starter or end index set: start_index = " << start_index << ", end_index=" << end_index << ", expected max index " << m_db_blocks.size() - 1);
|
||||
return true;
|
||||
}
|
||||
std::map<std::string, vote_on_proposal> summary;
|
||||
|
||||
for (size_t i = start_index; i < m_db_blocks.size() && i < end_index; i++)
|
||||
{
|
||||
auto block_ptr = m_db_blocks[i];
|
||||
//only coin holders can vote
|
||||
if(!is_pos_block(block_ptr->bl))
|
||||
continue;
|
||||
r.total_pos_blocks++;
|
||||
|
||||
extra_user_data eud = AUTO_VAL_INIT(eud);
|
||||
if (!get_type_in_variant_container(block_ptr->bl.miner_tx.extra, eud))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::list<std::pair<std::string, bool>> votes;
|
||||
if (!currency::parse_vote(eud.buff, votes))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (const auto& v : votes)
|
||||
{
|
||||
if (v.second)
|
||||
summary[v.first].yes++;
|
||||
else
|
||||
summary[v.first].no++;
|
||||
}
|
||||
}
|
||||
for (const auto s_entry : summary)
|
||||
{
|
||||
r.votes.push_back(s_entry.second);
|
||||
r.votes.back().proposal_id = s_entry.first;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
std::string blockchain_storage::get_blockchain_string(uint64_t start_index, uint64_t end_index) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
|
@ -3462,6 +3507,17 @@ std::string blockchain_storage::get_alias_by_address(const account_public_addres
|
|||
return "";
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
std::set<std::string> blockchain_storage::get_aliases_by_address(const account_public_address& addr)const
|
||||
{
|
||||
auto alias_ptr = m_db_addr_to_alias.find(addr);
|
||||
if (alias_ptr && alias_ptr->size())
|
||||
{
|
||||
return *(alias_ptr);
|
||||
}
|
||||
|
||||
return std::set<std::string>();
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::pop_alias_info(const extra_alias_entry& ai)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
|
@ -3651,15 +3707,6 @@ uint64_t blockchain_storage::validate_alias_reward(const transaction& tx, const
|
|||
//validate the price had been paid
|
||||
uint64_t found_alias_reward = get_amount_for_zero_pubkeys(tx);
|
||||
|
||||
//@#@
|
||||
//work around for net 68's generation
|
||||
#if CURRENCY_FORMATION_VERSION == 68
|
||||
if (alias == "bhrfrrrtret" && get_transaction_hash(tx) == epee::string_tools::parse_tpod_from_hex_string<crypto::hash>("760b85546678d2235a1843e18d8a016a2e4d9b8273cc4d7c09bebff1f6fa7eaf") )
|
||||
return true;
|
||||
if (alias == "test-420" && get_transaction_hash(tx) == epee::string_tools::parse_tpod_from_hex_string<crypto::hash>("10f8a2539b2551bd0919bf7e3b1dfbae7553eca63e58cd2264ae60f90030edf8"))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
CHECK_AND_ASSERT_MES(found_alias_reward >= fee_for_alias, false, "registration of alias '"
|
||||
<< alias << "' goes with a reward of " << print_money(found_alias_reward) << " which is less than expected: " << print_money(fee_for_alias)
|
||||
<<"(fee median: " << get_tx_fee_median() << ")"
|
||||
|
|
|
|||
|
|
@ -279,6 +279,7 @@ namespace currency
|
|||
bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<uint64_t>& indexs)const;
|
||||
bool get_alias_info(const std::string& alias, extra_alias_entry_base& info)const;
|
||||
std::string get_alias_by_address(const account_public_address& addr)const;
|
||||
std::set<std::string> get_aliases_by_address(const account_public_address& addr)const;
|
||||
template<typename cb_t>
|
||||
bool enumerate_aliases(cb_t cb) const;
|
||||
template<typename cb_t>
|
||||
|
|
@ -450,6 +451,7 @@ namespace currency
|
|||
void serialize(archive_t & ar, const unsigned int version);
|
||||
bool get_est_height_from_date(uint64_t date, uint64_t& res_h)const;
|
||||
|
||||
bool get_pos_votes(uint64_t start_h, uint64_t end_h, vote_results& r);
|
||||
|
||||
//debug functions
|
||||
bool validate_blockchain_prev_links(size_t last_n_blocks_to_check = 10) const;
|
||||
|
|
|
|||
|
|
@ -154,6 +154,28 @@ namespace currency
|
|||
transactions_map onboard_transactions;
|
||||
};
|
||||
|
||||
struct vote_on_proposal
|
||||
{
|
||||
std::string proposal_id;
|
||||
uint64_t yes;
|
||||
uint64_t no;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(proposal_id)
|
||||
KV_SERIALIZE(yes)
|
||||
KV_SERIALIZE(no)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct vote_results
|
||||
{
|
||||
uint64_t total_pos_blocks; //total pos blocks in a given range
|
||||
std::list<vote_on_proposal> votes;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(total_pos_blocks)
|
||||
KV_SERIALIZE(votes)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -30,6 +30,8 @@
|
|||
#define HF1_BLOCK_MAJOR_VERSION 1
|
||||
#define CURRENT_BLOCK_MAJOR_VERSION 2
|
||||
|
||||
#define CURRENCY_DEFAULT_DECOY_SET_SIZE 10
|
||||
|
||||
#define CURRENT_BLOCK_MINOR_VERSION 0
|
||||
#define CURRENCY_BLOCK_FUTURE_TIME_LIMIT 60*60*2
|
||||
#define CURRENCY_POS_BLOCK_FUTURE_TIME_LIMIT 60*20
|
||||
|
|
@ -214,6 +216,7 @@
|
|||
#define GUI_INTERNAL_CONFIG2 "gui_internal_config.json"
|
||||
#define GUI_IPC_MESSAGE_CHANNEL_NAME CURRENCY_NAME_BASE "_message_que"
|
||||
|
||||
#define CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME "voting_config.json"
|
||||
|
||||
|
||||
#define CURRENT_TRANSACTION_CHAIN_ENTRY_ARCHIVE_VER 3
|
||||
|
|
|
|||
|
|
@ -188,14 +188,9 @@ namespace currency
|
|||
|
||||
if (pos)
|
||||
{
|
||||
txin_to_key posin;
|
||||
posin.amount = pe.amount;
|
||||
posin.key_offsets.push_back(pe.index);
|
||||
posin.k_image = pe.keyimage;
|
||||
tx.vin.push_back(posin);
|
||||
//reserve place for ring signature
|
||||
tx.signatures.resize(1);
|
||||
tx.signatures[0].resize(posin.key_offsets.size());
|
||||
// just placeholders, they will be filled in wallet2::prepare_and_sign_pos_block()
|
||||
tx.vin.emplace_back(std::move(txin_to_key()));
|
||||
tx.signatures.emplace_back();
|
||||
}
|
||||
|
||||
uint64_t no = 0;
|
||||
|
|
@ -1615,6 +1610,35 @@ namespace currency
|
|||
return timestamp;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_vote(const std::string& json_, std::list<std::pair<std::string, bool>>& votes)
|
||||
{
|
||||
//do preliminary check of text if it looks like json
|
||||
std::string::size_type pos = json_.find('{');
|
||||
if (pos == std::string::npos)
|
||||
return false;
|
||||
std::string json = json_.substr(pos);
|
||||
|
||||
epee::serialization::portable_storage ps;
|
||||
bool rs = ps.load_from_json(json);
|
||||
if (!rs)
|
||||
return false;
|
||||
|
||||
|
||||
|
||||
auto cb = [&](const std::string& name, const epee::serialization::storage_entry& entry) {
|
||||
if (entry.type() == typeid(uint64_t))
|
||||
{
|
||||
bool vote = boost::get<uint64_t>(entry) ? true : false;
|
||||
votes.push_back(std::make_pair(epee::string_encoding::toupper(name), vote));
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
ps.enum_entries(nullptr, cb);
|
||||
return true;
|
||||
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
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 */)
|
||||
{
|
||||
#define LOC_CHK(cond, msg) CHECK_AND_ASSERT_MES(cond, false, msg << ", ms input index: " << ms_input_index << ", tx: " << get_transaction_hash(tx) << ", source tx: " << get_transaction_hash(source_tx))
|
||||
|
|
|
|||
|
|
@ -362,7 +362,10 @@ namespace currency
|
|||
bool fill_block_rpc_details(block_rpc_extended_info& pei_rpc, const block_extended_info& bei_chain, const crypto::hash& h);
|
||||
void append_per_block_increments_for_tx(const transaction& tx, std::unordered_map<uint64_t, uint32_t>& gindices);
|
||||
std::string get_word_from_timstamp(uint64_t timestamp, bool use_password);
|
||||
uint64_t get_timstamp_from_word(std::string word, bool& password_used, const std::string& buff);
|
||||
uint64_t get_timstamp_from_word(std::string word, bool& password_used);
|
||||
bool parse_vote(const std::string& buff, std::list<std::pair<std::string, bool>>& votes);
|
||||
|
||||
std::string generate_origin_for_htlc(const txout_htlc& htlc, const account_keys& acc_keys);
|
||||
template<class t_txin_v>
|
||||
typename std::conditional<std::is_const<t_txin_v>::value, const std::vector<txin_etc_details_v>, std::vector<txin_etc_details_v> >::type& get_txin_etc_options(t_txin_v& in)
|
||||
|
|
|
|||
|
|
@ -631,6 +631,18 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_get_votes(const COMMAND_RPC_GET_VOTES::request& req, COMMAND_RPC_GET_VOTES::response& res, connection_context& cntx)
|
||||
{
|
||||
if (!m_core.get_blockchain_storage().get_pos_votes(req.h_start, req.h_end, res.votes))
|
||||
{
|
||||
res.status = API_RETURN_CODE_INTERNAL_ERROR;
|
||||
res.error_code = "Internal error";
|
||||
return true;
|
||||
}
|
||||
res.status = API_RETURN_CODE_OK;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_get_main_block_details(const COMMAND_RPC_GET_BLOCK_DETAILS::request& req, COMMAND_RPC_GET_BLOCK_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx)
|
||||
{
|
||||
if (!m_core.get_blockchain_storage().get_main_block_rpc_details(req.id, res.block_details))
|
||||
|
|
@ -1286,7 +1298,7 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_alias_by_address(const COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& req, COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx)
|
||||
bool core_rpc_server::on_aliases_by_address(const COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& req, COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx)
|
||||
{
|
||||
account_public_address addr = AUTO_VAL_INIT(addr);
|
||||
if (!get_account_address_from_str(addr, req))
|
||||
|
|
@ -1298,22 +1310,28 @@ namespace currency
|
|||
COMMAND_RPC_GET_ALIAS_DETAILS::request req2 = AUTO_VAL_INIT(req2);
|
||||
COMMAND_RPC_GET_ALIAS_DETAILS::response res2 = AUTO_VAL_INIT(res2);
|
||||
|
||||
req2.alias = m_core.get_blockchain_storage().get_alias_by_address(addr);
|
||||
if (!req2.alias.size())
|
||||
std::set<std::string> aliases = m_core.get_blockchain_storage().get_aliases_by_address(addr);
|
||||
|
||||
if (!aliases.size())
|
||||
{
|
||||
res.status = API_RETURN_CODE_NOT_FOUND;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool r = this->on_get_alias_details(req2, res2, error_resp, cntx);
|
||||
if (!r || res2.status != API_RETURN_CODE_OK)
|
||||
for (auto it = aliases.begin(); it != aliases.end(); it++)
|
||||
{
|
||||
res.status = API_RETURN_CODE_FAIL;
|
||||
return true;
|
||||
}
|
||||
req2.alias = *it;
|
||||
bool r = this->on_get_alias_details(req2, res2, error_resp, cntx);
|
||||
if (!r || res2.status != API_RETURN_CODE_OK)
|
||||
{
|
||||
res.status = API_RETURN_CODE_FAIL;
|
||||
return true;
|
||||
}
|
||||
res.alias_info_list.push_back(alias_rpc_details());
|
||||
res.alias_info_list.back().details = res2.alias_details;
|
||||
res.alias_info_list.back().alias = req2.alias;
|
||||
|
||||
res.alias_info.details = res2.alias_details;
|
||||
res.alias_info.alias = req2.alias;
|
||||
}
|
||||
res.status = API_RETURN_CODE_OK;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ namespace currency
|
|||
bool on_get_alias_details(const COMMAND_RPC_GET_ALIAS_DETAILS::request& req, COMMAND_RPC_GET_ALIAS_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_get_all_aliases(const COMMAND_RPC_GET_ALL_ALIASES::request& req, COMMAND_RPC_GET_ALL_ALIASES::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_get_aliases(const COMMAND_RPC_GET_ALIASES::request& req, COMMAND_RPC_GET_ALIASES::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_alias_by_address(const COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& req, COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_aliases_by_address(const COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& req, COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_get_alias_reward(const COMMAND_RPC_GET_ALIAS_REWARD::request& req, COMMAND_RPC_GET_ALIAS_REWARD::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_get_addendums(const COMMAND_RPC_GET_ADDENDUMS::request& req, COMMAND_RPC_GET_ADDENDUMS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_reset_transaction_pool(const COMMAND_RPC_RESET_TX_POOL::request& req, COMMAND_RPC_RESET_TX_POOL::response& res, connection_context& cntx);
|
||||
|
|
@ -85,6 +85,7 @@ namespace currency
|
|||
bool on_get_pool_txs_brief_details(const COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS::request& req, COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS::response& res, connection_context& cntx);
|
||||
bool on_get_all_pool_tx_list(const COMMAND_RPC_GET_ALL_POOL_TX_LIST::request& req, COMMAND_RPC_GET_ALL_POOL_TX_LIST::response& res, connection_context& cntx);
|
||||
bool on_get_pool_info(const COMMAND_RPC_GET_POOL_INFO::request& req, COMMAND_RPC_GET_POOL_INFO::response& res, connection_context& cntx);
|
||||
bool on_get_votes(const COMMAND_RPC_GET_VOTES::request& req, COMMAND_RPC_GET_VOTES::response& res, connection_context& cntx);
|
||||
|
||||
bool on_get_main_block_details(const COMMAND_RPC_GET_BLOCK_DETAILS::request& req, COMMAND_RPC_GET_BLOCK_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_get_alt_block_details(const COMMAND_RPC_GET_BLOCK_DETAILS::request& req, COMMAND_RPC_GET_BLOCK_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
|
|
@ -134,7 +135,7 @@ namespace currency
|
|||
MAP_JON_RPC_WE("getblockheaderbyhash", on_get_block_header_by_hash, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH)
|
||||
MAP_JON_RPC_WE("getblockheaderbyheight", on_get_block_header_by_height, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT)
|
||||
MAP_JON_RPC_WE("get_alias_details", on_get_alias_details, COMMAND_RPC_GET_ALIAS_DETAILS)
|
||||
MAP_JON_RPC_WE("get_alias_by_address", on_alias_by_address, COMMAND_RPC_GET_ALIASES_BY_ADDRESS)
|
||||
MAP_JON_RPC_WE("get_alias_by_address", on_aliases_by_address, COMMAND_RPC_GET_ALIASES_BY_ADDRESS)
|
||||
MAP_JON_RPC_WE("get_alias_reward", on_get_alias_reward, COMMAND_RPC_GET_ALIAS_REWARD)
|
||||
MAP_JON_RPC ("get_est_height_from_date", on_get_est_height_from_date, COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE)
|
||||
//block explorer api
|
||||
|
|
@ -151,6 +152,7 @@ namespace currency
|
|||
MAP_JON_RPC ("get_all_pool_tx_list", on_get_all_pool_tx_list, COMMAND_RPC_GET_ALL_POOL_TX_LIST)
|
||||
MAP_JON_RPC ("get_pool_info", on_get_pool_info, COMMAND_RPC_GET_POOL_INFO)
|
||||
MAP_JON_RPC ("getrandom_outs", on_get_random_outs, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS)
|
||||
MAP_JON_RPC ("get_votes", on_get_votes, COMMAND_RPC_GET_VOTES)
|
||||
|
||||
MAP_JON_RPC_WE("get_main_block_details", on_get_main_block_details, COMMAND_RPC_GET_BLOCK_DETAILS)
|
||||
MAP_JON_RPC_WE("get_alt_block_details", on_get_alt_block_details, COMMAND_RPC_GET_BLOCK_DETAILS)
|
||||
|
|
|
|||
|
|
@ -83,6 +83,34 @@ namespace currency
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
struct COMMAND_RPC_GET_VOTES
|
||||
{
|
||||
struct request
|
||||
{
|
||||
uint64_t h_start;
|
||||
uint64_t h_end;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(h_start)
|
||||
KV_SERIALIZE(h_end)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string status;
|
||||
std::string error_code;
|
||||
vote_results votes;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status)
|
||||
KV_SERIALIZE(error_code)
|
||||
KV_SERIALIZE(votes)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_GET_HEIGHT
|
||||
{
|
||||
struct request
|
||||
|
|
@ -331,6 +359,10 @@ namespace currency
|
|||
#pragma pack (push, 1)
|
||||
struct out_entry
|
||||
{
|
||||
out_entry() = default;
|
||||
out_entry(uint64_t global_amount_index, const crypto::public_key& stealth_address)
|
||||
: global_amount_index(global_amount_index), out_key(stealth_address)
|
||||
{}
|
||||
uint64_t global_amount_index;
|
||||
crypto::public_key out_key;
|
||||
};
|
||||
|
|
@ -1069,11 +1101,11 @@ namespace currency
|
|||
struct response
|
||||
{
|
||||
//std::string alias;
|
||||
alias_rpc_details alias_info;
|
||||
std::vector<alias_rpc_details> alias_info_list;
|
||||
std::string status;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(alias_info)
|
||||
KV_SERIALIZE(alias_info_list)
|
||||
KV_SERIALIZE(status)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ template <>
|
|||
struct binary_archive<false> : public binary_archive_base<std::istream, false>
|
||||
{
|
||||
explicit binary_archive(stream_type &s) : base_type(s) {
|
||||
stream_type::streampos pos = stream_.tellg();
|
||||
stream_type::pos_type pos = stream_.tellg();
|
||||
stream_.seekg(0, std::ios_base::end);
|
||||
eof_pos_ = stream_.tellg();
|
||||
stream_.seekg(pos);
|
||||
|
|
|
|||
|
|
@ -49,14 +49,16 @@ namespace
|
|||
const command_line::arg_descriptor<bool> arg_dont_refresh ( "no-refresh", "Do not refresh after load");
|
||||
const command_line::arg_descriptor<bool> arg_dont_set_date ( "no-set-creation-date", "Do not set wallet creation date", false);
|
||||
const command_line::arg_descriptor<int> arg_daemon_port ("daemon-port", "Use daemon instance at port <arg> instead of default", 0);
|
||||
const command_line::arg_descriptor<uint32_t> arg_log_level ("set-log", "");
|
||||
//const command_line::arg_descriptor<uint32_t> arg_log_level ("set-log", "");
|
||||
const command_line::arg_descriptor<bool> arg_do_pos_mining ( "do-pos-mining", "Do PoS mining", false);
|
||||
const command_line::arg_descriptor<std::string> arg_pos_mining_reward_address ( "pos-mining-reward-address", "Block reward will be sent to the giving address if specified", "" );
|
||||
const command_line::arg_descriptor<std::string> arg_restore_wallet ( "restore-wallet", "Restore wallet from seed phrase or tracking seed and save it to <arg>", "" );
|
||||
const command_line::arg_descriptor<bool> arg_offline_mode ( "offline-mode", "Don't connect to daemon, work offline (for cold-signing process)");
|
||||
const command_line::arg_descriptor<std::string> arg_scan_for_wallet ( "scan-for-wallet", "");
|
||||
const command_line::arg_descriptor<std::string> arg_addr_to_compare ( "addr-to-compare", "");
|
||||
const command_line::arg_descriptor<bool> arg_disable_tor_relay ( "disable-tor-relay", "Do PoS mining", false);
|
||||
const command_line::arg_descriptor<bool> arg_disable_tor_relay ( "disable-tor-relay", "Disable TOR relay", false);
|
||||
const command_line::arg_descriptor<unsigned int> arg_set_timeout("set-timeout", "Set timeout for the wallet");
|
||||
const command_line::arg_descriptor<std::string> arg_voting_config_file("voting-config-file", "Set voting config instead of getting if from daemon", "");
|
||||
|
||||
const command_line::arg_descriptor< std::vector<std::string> > arg_command ("command", "");
|
||||
|
||||
|
|
@ -158,6 +160,26 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
void display_vote_info(tools::wallet2& w)
|
||||
{
|
||||
const tools::wallet_public::wallet_vote_config& votes = w.get_current_votes();
|
||||
if (votes.entries.size())
|
||||
{
|
||||
message_writer(epee::log_space::console_color_magenta, true) << "VOTING SET LOADED:";
|
||||
for (const auto& e : votes.entries)
|
||||
{
|
||||
epee::log_space::console_colors color = epee::log_space::console_color_green;
|
||||
if (e.h_end < w.get_top_block_height())
|
||||
{
|
||||
color = epee::log_space::console_color_white;
|
||||
}
|
||||
|
||||
message_writer(color, true) << "\t\t" << e.proposal_id << "\t\t" << (e.vote ? "1" : "0") << "\t\t(" << e.h_start << " - " << e.h_end << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string simple_wallet::get_commands_str()
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
|
@ -183,7 +205,8 @@ simple_wallet::simple_wallet()
|
|||
m_cmd_binder.set_handler("start_mining", boost::bind(&simple_wallet::start_mining, this, ph::_1), "start_mining <threads_count> - Start mining in daemon");
|
||||
m_cmd_binder.set_handler("stop_mining", boost::bind(&simple_wallet::stop_mining, this, ph::_1), "Stop mining in daemon");
|
||||
m_cmd_binder.set_handler("refresh", boost::bind(&simple_wallet::refresh, this, ph::_1), "Resynchronize transactions and balance");
|
||||
m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, ph::_1), "Show current wallet balance");
|
||||
m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, ph::_1), "Show current wallet balance");
|
||||
m_cmd_binder.set_handler("show_staking_history", boost::bind(&simple_wallet::show_staking_history, this, ph::_1), "show_staking_history [2] - Show staking transfers, if option provided - number of days for history to display");
|
||||
m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, ph::_1), "incoming_transfers [available|unavailable] - Show incoming transfers - all of them or filter them by availability");
|
||||
m_cmd_binder.set_handler("incoming_counts", boost::bind(&simple_wallet::show_incoming_transfers_counts, this, ph::_1), "incoming_transfers counts");
|
||||
m_cmd_binder.set_handler("list_recent_transfers", boost::bind(&simple_wallet::list_recent_transfers, this, ph::_1), "list_recent_transfers [offset] [count] - Show recent maximum 1000 transfers, offset default = 0, count default = 100 ");
|
||||
|
|
@ -261,6 +284,29 @@ bool simple_wallet::set_log(const std::vector<std::string> &args)
|
|||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void process_wallet_command_line_params(const po::variables_map& vm, tools::wallet2& wal, bool is_server_mode = true)
|
||||
{
|
||||
if (command_line::has_arg(vm, arg_disable_tor_relay))
|
||||
{
|
||||
wal.set_disable_tor_relay(command_line::get_arg(vm, arg_disable_tor_relay));
|
||||
message_writer(epee::log_space::console_color_default, true, std::string(), LOG_LEVEL_0) << "Notice: Relaying transactions over TOR disabled with command line parameter";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_server_mode)
|
||||
{
|
||||
//disable TOR by default for server-mode, to avoid potential sporadic errors due to TOR connectivity fails
|
||||
wal.set_disable_tor_relay(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (command_line::has_arg(vm, arg_set_timeout))
|
||||
{
|
||||
wal.set_connectivity_options(command_line::get_arg(vm, arg_set_timeout));
|
||||
}
|
||||
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
||||
{
|
||||
handle_command_line(vm);
|
||||
|
|
@ -305,7 +351,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||
m_do_refresh_after_load = false;
|
||||
}
|
||||
|
||||
|
||||
bool was_open = false;
|
||||
if (!m_generate_new.empty())
|
||||
{
|
||||
bool r = new_wallet(m_generate_new, pwd_container.password(), false);
|
||||
|
|
@ -356,12 +402,14 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||
{
|
||||
bool r = open_wallet(m_wallet_file, pwd_container.password());
|
||||
CHECK_AND_ASSERT_MES(r, false, "could not open account");
|
||||
was_open = true;
|
||||
}
|
||||
if (m_disable_tor)
|
||||
{
|
||||
m_wallet->set_disable_tor_relay(true);
|
||||
message_writer(epee::log_space::console_color_default, true, std::string(), LOG_LEVEL_0) << "Notice: Relaying transactions over TOR disabled with command line parameter";
|
||||
}
|
||||
process_wallet_command_line_params(vm, *m_wallet, false);
|
||||
|
||||
m_wallet->init(m_daemon_address);
|
||||
|
||||
if (was_open && (m_do_refresh_after_load && !m_offline_mode))
|
||||
refresh(std::vector<std::string>());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -386,6 +434,7 @@ void simple_wallet::handle_command_line(const boost::program_options::variables_
|
|||
m_do_pos_mining = command_line::get_arg(vm, arg_do_pos_mining);
|
||||
m_restore_wallet = command_line::get_arg(vm, arg_restore_wallet);
|
||||
m_disable_tor = command_line::get_arg(vm, arg_disable_tor_relay);
|
||||
m_voting_config_file = command_line::get_arg(vm, arg_voting_config_file);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::try_connect_to_daemon()
|
||||
|
|
@ -406,18 +455,21 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
|
|||
|
||||
m_wallet.reset(new tools::wallet2());
|
||||
m_wallet->callback(this->shared_from_this());
|
||||
if (!m_voting_config_file.empty())
|
||||
m_wallet->set_votes_config_path(m_voting_config_file);
|
||||
|
||||
m_wallet->set_do_rise_transfer(false);
|
||||
try
|
||||
{
|
||||
m_wallet->generate(epee::string_encoding::utf8_to_wstring(m_wallet_file), password, create_auditable_wallet);
|
||||
message_writer(epee::log_space::console_color_white, true) << "Generated new " << (create_auditable_wallet ? "AUDITABLE" : "") << " wallet: " << m_wallet->get_account().get_public_address_str();
|
||||
display_vote_info(*m_wallet);
|
||||
std::cout << "view key: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().view_secret_key) << std::endl << std::flush;
|
||||
if (m_wallet->is_auditable())
|
||||
std::cout << "tracking seed: " << std::endl << m_wallet->get_account().get_tracking_seed() << std::endl << std::flush;
|
||||
if (m_do_not_set_date)
|
||||
m_wallet->reset_creation_time(0);
|
||||
|
||||
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
|
@ -425,9 +477,6 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
|
|||
return false;
|
||||
}
|
||||
|
||||
m_wallet->init(m_daemon_address);
|
||||
|
||||
|
||||
success_msg_writer() <<
|
||||
"**********************************************************************\n" <<
|
||||
"Your wallet has been generated.\n" <<
|
||||
|
|
@ -441,6 +490,9 @@ bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::st
|
|||
|
||||
m_wallet.reset(new tools::wallet2());
|
||||
m_wallet->callback(this->shared_from_this());
|
||||
if (!m_voting_config_file.empty())
|
||||
m_wallet->set_votes_config_path(m_voting_config_file);
|
||||
|
||||
m_wallet->set_do_rise_transfer(true);
|
||||
try
|
||||
{
|
||||
|
|
@ -459,6 +511,7 @@ bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::st
|
|||
if (m_wallet->is_auditable())
|
||||
std::cout << "tracking seed: " << std::endl << m_wallet->get_account().get_tracking_seed() << std::endl << std::flush;
|
||||
}
|
||||
display_vote_info(*m_wallet);
|
||||
if (m_do_not_set_date)
|
||||
m_wallet->reset_creation_time(0);
|
||||
}
|
||||
|
|
@ -472,7 +525,6 @@ bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::st
|
|||
fail_msg_writer() << "failed to restore wallet, check your " << (tracking_wallet ? "tracking seed!" : "seed phrase!") << ENDL;
|
||||
return false;
|
||||
}
|
||||
m_wallet->init(m_daemon_address);
|
||||
|
||||
success_msg_writer() <<
|
||||
"**********************************************************************\n" <<
|
||||
|
|
@ -486,11 +538,15 @@ bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::st
|
|||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
bool simple_wallet::open_wallet(const string &wallet_file, const std::string& password)
|
||||
{
|
||||
m_wallet_file = wallet_file;
|
||||
m_wallet.reset(new tools::wallet2());
|
||||
m_wallet->callback(shared_from_this());
|
||||
if (!m_voting_config_file.empty())
|
||||
m_wallet->set_votes_config_path(m_voting_config_file);
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
|
@ -498,6 +554,7 @@ bool simple_wallet::open_wallet(const string &wallet_file, const std::string& pa
|
|||
{
|
||||
m_wallet->load(epee::string_encoding::utf8_to_wstring(m_wallet_file), password);
|
||||
message_writer(epee::log_space::console_color_white, true) << "Opened" << (m_wallet->is_auditable() ? " auditable" : "") << (m_wallet->is_watch_only() ? " watch-only" : "") << " wallet: " << m_wallet->get_account().get_public_address_str();
|
||||
display_vote_info(*m_wallet);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -514,12 +571,6 @@ bool simple_wallet::open_wallet(const string &wallet_file, const std::string& pa
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
m_wallet->init(m_daemon_address);
|
||||
|
||||
if (m_do_refresh_after_load && !m_offline_mode)
|
||||
refresh(std::vector<std::string>());
|
||||
|
||||
success_msg_writer() <<
|
||||
"**********************************************************************\n" <<
|
||||
"Use \"help\" command to see the list of available commands.\n" <<
|
||||
|
|
@ -774,9 +825,9 @@ bool print_wti(const tools::wallet_public::wallet_transfer_info& wti)
|
|||
|
||||
static const std::string separator = ", ";
|
||||
std::string remote_side;
|
||||
if (!wti.recipients_aliases.empty())
|
||||
if (!wti.remote_aliases.empty())
|
||||
{
|
||||
for (auto it : wti.recipients_aliases)
|
||||
for (auto it : wti.remote_aliases)
|
||||
remote_side += remote_side.empty() ? it : (separator + it);
|
||||
}
|
||||
else
|
||||
|
|
@ -812,15 +863,13 @@ bool simple_wallet::list_recent_transfers(const std::vector<std::string>& args)
|
|||
success_msg_writer() << "Unconfirmed transfers: ";
|
||||
for (auto & wti : unconfirmed)
|
||||
{
|
||||
if (!wti.fee)
|
||||
wti.fee = currency::get_tx_fee(wti.tx);
|
||||
wti.fee = currency::get_tx_fee(wti.tx);
|
||||
print_wti(wti);
|
||||
}
|
||||
success_msg_writer() << "Recent transfers: ";
|
||||
for (auto & wti : recent)
|
||||
{
|
||||
if (!wti.fee)
|
||||
wti.fee = currency::get_tx_fee(wti.tx);
|
||||
wti.fee = currency::get_tx_fee(wti.tx);
|
||||
print_wti(wti);
|
||||
}
|
||||
return true;
|
||||
|
|
@ -892,6 +941,70 @@ bool simple_wallet::dump_key_images(const std::vector<std::string>& args)
|
|||
success_msg_writer() << "Storing text to dump_keyimages.txt....";
|
||||
file_io_utils::save_string_to_file(log_space::log_singletone::get_default_log_folder() + "/dump_keyimages.txt", ss.str());
|
||||
success_msg_writer() << "Done....";
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::show_staking_history(const std::vector<std::string>& args)
|
||||
{
|
||||
uint64_t n_days = 0;
|
||||
if (!args.empty())
|
||||
{
|
||||
if (!epee::string_tools::get_xtype_from_string(n_days, args[0]))
|
||||
{
|
||||
fail_msg_writer() << "Unknown amount of days to list";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
tools::wallet2::transfer_container transfers;
|
||||
m_wallet->get_transfers(transfers);
|
||||
|
||||
uint64_t timestamp = 0;
|
||||
|
||||
if (n_days)
|
||||
timestamp = static_cast<uint64_t>(time(nullptr)) - (n_days * 60 * 60 * 24);
|
||||
|
||||
uint64_t amount_total_staked = 0;
|
||||
bool transfers_found = false;
|
||||
for (auto it = transfers.rbegin(); it != transfers.rend(); it++)
|
||||
{
|
||||
const auto& td = *it;
|
||||
|
||||
if (timestamp && td.m_ptx_wallet_info->m_block_timestamp < timestamp)
|
||||
break;
|
||||
|
||||
if (!(td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER))
|
||||
continue;
|
||||
|
||||
bool pos_coinbase = false;
|
||||
is_coinbase(td.m_ptx_wallet_info->m_tx, pos_coinbase);
|
||||
if (!pos_coinbase)
|
||||
continue;
|
||||
|
||||
if (!transfers_found)
|
||||
{
|
||||
message_writer() << " amount \tspent\tglobal index\t tx id";
|
||||
transfers_found = true;
|
||||
}
|
||||
amount_total_staked += td.amount();
|
||||
message_writer(static_cast<bool>(td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_SPENT) ? epee::log_space::console_color_magenta : epee::log_space::console_color_green, false) <<
|
||||
std::setw(21) << print_money(td.amount()) << '\t' <<
|
||||
std::setw(3) << (static_cast<bool>(td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_SPENT) ? 'T' : 'F') << " \t" <<
|
||||
std::setw(12) << td.m_global_output_index << '\t' <<
|
||||
get_transaction_hash(td.m_ptx_wallet_info->m_tx) << "[" << td.m_ptx_wallet_info->m_block_height << "] unlocked: " << (m_wallet->is_transfer_unlocked(td) ? 'T' : 'F');
|
||||
}
|
||||
|
||||
if (!transfers_found)
|
||||
{
|
||||
success_msg_writer() << "No staking transactions";
|
||||
}
|
||||
else
|
||||
{
|
||||
success_msg_writer() << "Total staked: " << print_money(amount_total_staked);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
@ -1946,6 +2059,7 @@ bool search_for_wallet_file(const std::wstring &search_here/*, const std::string
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
#ifdef WIN32
|
||||
int wmain( int argc, wchar_t* argv_w[ ], wchar_t* envp[ ] )
|
||||
|
|
@ -1994,7 +2108,7 @@ int main(int argc, char* argv[])
|
|||
command_line::add_arg(desc_params, arg_daemon_host);
|
||||
command_line::add_arg(desc_params, arg_daemon_port);
|
||||
command_line::add_arg(desc_params, arg_command);
|
||||
command_line::add_arg(desc_params, arg_log_level);
|
||||
//command_line::add_arg(desc_params, arg_log_level);
|
||||
command_line::add_arg(desc_params, arg_dont_refresh);
|
||||
command_line::add_arg(desc_params, arg_dont_set_date);
|
||||
command_line::add_arg(desc_params, arg_do_pos_mining);
|
||||
|
|
@ -2006,6 +2120,9 @@ int main(int argc, char* argv[])
|
|||
command_line::add_arg(desc_params, arg_scan_for_wallet);
|
||||
command_line::add_arg(desc_params, arg_addr_to_compare);
|
||||
command_line::add_arg(desc_params, arg_disable_tor_relay);
|
||||
command_line::add_arg(desc_params, arg_set_timeout);
|
||||
command_line::add_arg(desc_params, arg_voting_config_file);
|
||||
|
||||
|
||||
|
||||
tools::wallet_rpc_server::init_options(desc_params);
|
||||
|
|
@ -2043,7 +2160,7 @@ int main(int argc, char* argv[])
|
|||
return EXIT_FAILURE;
|
||||
|
||||
//set up logging options
|
||||
log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2);
|
||||
log_space::get_set_log_detalisation_level(true, LOG_LEVEL_0);
|
||||
boost::filesystem::path log_file_path(command_line::get_arg(vm, command_line::arg_log_file));
|
||||
if (log_file_path.empty())
|
||||
log_file_path = log_space::log_singletone::get_default_log_file();
|
||||
|
|
@ -2052,15 +2169,13 @@ int main(int argc, char* argv[])
|
|||
log_space::log_singletone::add_logger(LOGGER_FILE, log_file_path.filename().string().c_str(), log_dir.c_str(), LOG_LEVEL_4);
|
||||
message_writer(epee::log_space::console_color_white, true) << CURRENCY_NAME << " wallet v" << PROJECT_VERSION_LONG;
|
||||
|
||||
if (command_line::has_arg(vm, arg_log_level))
|
||||
{
|
||||
LOG_PRINT_L0("Setting log level = " << command_line::get_arg(vm, arg_log_level));
|
||||
log_space::get_set_log_detalisation_level(true, command_line::get_arg(vm, arg_log_level));
|
||||
}
|
||||
if (command_line::has_arg(vm, command_line::arg_log_level))
|
||||
{
|
||||
LOG_PRINT_L0("Setting log level = " << command_line::get_arg(vm, command_line::arg_log_level));
|
||||
log_space::get_set_log_detalisation_level(true, command_line::get_arg(vm, command_line::arg_log_level));
|
||||
int old_log_level = log_space::get_set_log_detalisation_level(false);
|
||||
int new_log_level = command_line::get_arg(vm, command_line::arg_log_level);
|
||||
log_space::get_set_log_detalisation_level(true, new_log_level);
|
||||
LOG_PRINT_L0("Log level changed: " << old_log_level << " -> " << new_log_level);
|
||||
message_writer(epee::log_space::console_color_white, true) << "Log level changed: " << old_log_level << " -> " << new_log_level;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2081,7 +2196,7 @@ int main(int argc, char* argv[])
|
|||
// runs wallet as RPC server
|
||||
log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_2);
|
||||
sw->set_offline_mode(offline_mode);
|
||||
LOG_PRINT_L0("Starting wallet RPC server...");
|
||||
LOG_PRINT_L0("Starting in RPC server mode...");
|
||||
|
||||
if (!command_line::has_arg(vm, arg_wallet_file) || command_line::get_arg(vm, arg_wallet_file).empty())
|
||||
{
|
||||
|
|
@ -2147,7 +2262,9 @@ int main(int argc, char* argv[])
|
|||
try
|
||||
{
|
||||
LOG_PRINT_L0("Initializing wallet...");
|
||||
process_wallet_command_line_params(vm, wal);
|
||||
wal.init(daemon_address);
|
||||
display_vote_info(wal);
|
||||
if (command_line::get_arg(vm, arg_generate_new_wallet).size() || command_line::get_arg(vm, arg_generate_new_auditable_wallet).size())
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
|
@ -2176,6 +2293,8 @@ int main(int argc, char* argv[])
|
|||
LOG_PRINT_YELLOW("PoS reward will be sent to another address: " << arg_pos_mining_reward_address_str, LOG_LEVEL_0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
tools::wallet_rpc_server wrpc(wal);
|
||||
bool r = wrpc.init(vm);
|
||||
|
|
@ -2204,7 +2323,7 @@ int main(int argc, char* argv[])
|
|||
if (command_line::get_arg(vm, arg_do_pos_mining))
|
||||
{
|
||||
// PoS mining can be turned on only in RPC server mode, please provide --rpc-bind-port to make this
|
||||
fail_msg_writer() << "PoS mining can be turned on only in RPC server mode, please provide --rpc-bind-port=PORT_NO to enable staking in simplewallet";
|
||||
fail_msg_writer() << "PoS mining can only be started in RPC server mode, please use command-line option --rpc-bind-port=<PORT_NUM> along with --do-pos-mining to enable staking";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ namespace currency
|
|||
bool dump_trunsfers(const std::vector<std::string>& args);
|
||||
bool dump_key_images(const std::vector<std::string>& args);
|
||||
bool show_incoming_transfers(const std::vector<std::string> &args);
|
||||
bool show_staking_history(const std::vector<std::string>& args);
|
||||
bool show_incoming_transfers_counts(const std::vector<std::string> &args);
|
||||
bool list_outputs(const std::vector<std::string> &args);
|
||||
bool show_payments(const std::vector<std::string> &args);
|
||||
|
|
@ -171,6 +172,7 @@ namespace currency
|
|||
bool m_offline_mode;
|
||||
bool m_disable_tor;
|
||||
std::string m_restore_wallet;
|
||||
std::string m_voting_config_file;
|
||||
|
||||
epee::console_handlers_binder m_cmd_binder;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@
|
|||
#define PROJECT_REVISION "2"
|
||||
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
|
||||
|
||||
#define PROJECT_VERSION_BUILD_NO 152
|
||||
#define PROJECT_VERSION_BUILD_NO 153
|
||||
#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 "]"
|
||||
|
|
|
|||
|
|
@ -184,11 +184,10 @@ namespace tools
|
|||
// m_plast_daemon_is_disconnected = plast_daemon_is_disconnected ? plast_daemon_is_disconnected : &m_last_daemon_is_disconnected_stub;
|
||||
// }
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool default_http_core_proxy::set_connectivity(unsigned int connection_timeout, size_t repeats_count)
|
||||
void default_http_core_proxy::set_connectivity(unsigned int connection_timeout, size_t repeats_count)
|
||||
{
|
||||
m_connection_timeout = connection_timeout;
|
||||
m_attempts_count = repeats_count;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
default_http_core_proxy::default_http_core_proxy(): //:m_plast_daemon_is_disconnected(&m_last_daemon_is_disconnected_stub),
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace tools
|
|||
|
||||
|
||||
bool set_connection_addr(const std::string& url) override;
|
||||
bool set_connectivity(unsigned int connection_timeout, size_t repeats_count);
|
||||
void set_connectivity(unsigned int connection_timeout, size_t repeats_count);
|
||||
bool call_COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES(const currency::COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& rqt, currency::COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GET_BLOCKS_FAST(const currency::COMMAND_RPC_GET_BLOCKS_FAST::request& rqt, currency::COMMAND_RPC_GET_BLOCKS_FAST::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GET_BLOCKS_DIRECT(const currency::COMMAND_RPC_GET_BLOCKS_DIRECT::request& rqt, currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& rsp) override;
|
||||
|
|
@ -56,7 +56,7 @@ namespace tools
|
|||
bool check_connection() override;
|
||||
bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id) override;
|
||||
|
||||
void set_plast_daemon_is_disconnected(std::atomic<bool> *plast_daemon_is_disconnected);
|
||||
void set_plast_daemon_is_disconnected(std::atomic<bool> *plast_daemon_is_disconnected);
|
||||
default_http_core_proxy();
|
||||
private:
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ namespace tools
|
|||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool call_COMMAND_RPC_GET_ALIASES_BY_ADDRESS(const currency::COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& req, currency::COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& res) override
|
||||
{
|
||||
return m_rpc.on_alias_by_address(req, res, m_err_stub, m_cntxt_stub);
|
||||
return m_rpc.on_aliases_by_address(req, res, m_err_stub, m_cntxt_stub);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) override
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ namespace tools
|
|||
std::shared_ptr<const proxy_diagnostic_info> get_proxy_diagnostic_info() const { return m_pdiganostic_info; }
|
||||
std::shared_ptr<proxy_diagnostic_info> get_editable_proxy_diagnostic_info() { return m_pdiganostic_info; }
|
||||
virtual bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id){ return false; }
|
||||
virtual void set_connectivity(unsigned int connection_timeout, size_t repeats_count) {}
|
||||
protected:
|
||||
std::shared_ptr<proxy_diagnostic_info> m_pdiganostic_info;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ using namespace epee;
|
|||
#include "currency_core/bc_offers_service_basic.h"
|
||||
#include "rpc/core_rpc_server_commands_defs.h"
|
||||
#include "misc_language.h"
|
||||
#include "common/util.h"
|
||||
|
||||
#include "common/boost_serialization_helper.h"
|
||||
#include "crypto/crypto.h"
|
||||
|
|
@ -65,9 +66,11 @@ namespace tools
|
|||
m_last_pow_block_h(0),
|
||||
m_minimum_height(WALLET_MINIMUM_HEIGHT_UNSET_CONST),
|
||||
m_pos_mint_packing_size(WALLET_DEFAULT_POS_MINT_PACKING_SIZE),
|
||||
m_required_decoys_count(CURRENCY_DEFAULT_DECOY_SET_SIZE),
|
||||
m_current_wallet_file_size(0),
|
||||
m_use_deffered_global_outputs(false),
|
||||
m_disable_tor_relay(false)
|
||||
m_disable_tor_relay(false),
|
||||
m_votes_config_path(tools::get_default_data_dir() + "/" + CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME)
|
||||
{
|
||||
m_core_runtime_config = currency::get_default_core_runtime_config();
|
||||
}
|
||||
|
|
@ -171,9 +174,22 @@ std::shared_ptr<wallet2::transaction_wallet_info> wallet2::transform_value_to_pt
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::init(const std::string& daemon_address)
|
||||
{
|
||||
m_miner_text_info = PROJECT_VERSION_LONG;
|
||||
//m_miner_text_info = PROJECT_VERSION_LONG;
|
||||
m_core_proxy->set_connection_addr(daemon_address);
|
||||
m_core_proxy->check_connection();
|
||||
|
||||
std::stringstream ss;
|
||||
const tools::wallet_public::wallet_vote_config& votes = this->get_current_votes();
|
||||
if (votes.entries.size())
|
||||
{
|
||||
ss << "VOTING SET LOADED:";
|
||||
for (const auto& e : votes.entries)
|
||||
{
|
||||
ss << "\t\t" << e.proposal_id << "\t\t" << (e.vote ? "1" : "0") << "\t\t(" << e.h_start << " - " << e.h_end << ")";
|
||||
}
|
||||
}
|
||||
WLT_LOG_L0(ss.str());
|
||||
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::set_core_proxy(const std::shared_ptr<i_core_proxy>& proxy)
|
||||
|
|
@ -318,8 +334,8 @@ void wallet2::fetch_tx_global_indixes(const std::list<std::reference_wrapper<con
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t height, const currency::block& b, const std::vector<uint64_t>* pglobal_indexes)
|
||||
{
|
||||
std::vector<std::string> recipients, recipients_aliases;
|
||||
process_unconfirmed(tx, recipients, recipients_aliases);
|
||||
std::vector<std::string> recipients, remote_aliases;
|
||||
process_unconfirmed(tx, recipients, remote_aliases);
|
||||
std::vector<size_t> outs;
|
||||
uint64_t tx_money_got_in_outs = 0;
|
||||
crypto::public_key tx_pub_key = null_pkey;
|
||||
|
|
@ -686,7 +702,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
{//this actually is transfer transaction, notify about spend
|
||||
if (tx_money_spent_in_ins > tx_money_got_in_outs)
|
||||
{//usual transfer
|
||||
handle_money_spent2(b, tx, tx_money_spent_in_ins - (tx_money_got_in_outs+get_tx_fee(tx)), mtd, recipients, recipients_aliases);
|
||||
handle_money_spent2(b, tx, tx_money_spent_in_ins - (tx_money_got_in_outs+get_tx_fee(tx)), mtd, recipients, remote_aliases);
|
||||
}
|
||||
else
|
||||
{//strange transfer, seems that in one transaction have transfers from different wallets.
|
||||
|
|
@ -709,7 +725,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
else if (mtd.spent_indices.size())
|
||||
{
|
||||
// multisig spend detected
|
||||
handle_money_spent2(b, tx, 0, mtd, recipients, recipients_aliases);
|
||||
handle_money_spent2(b, tx, 0, mtd, recipients, remote_aliases);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1318,27 +1334,27 @@ void wallet2::handle_money_spent2(const currency::block& b,
|
|||
uint64_t amount,
|
||||
const money_transfer2_details& td,
|
||||
const std::vector<std::string>& recipients,
|
||||
const std::vector<std::string>& recipients_aliases)
|
||||
const std::vector<std::string>& remote_aliases)
|
||||
{
|
||||
m_transfer_history.push_back(AUTO_VAL_INIT(wallet_public::wallet_transfer_info()));
|
||||
wallet_public::wallet_transfer_info& wti = m_transfer_history.back();
|
||||
wti.is_income = false;
|
||||
|
||||
wti.remote_addresses = recipients;
|
||||
wti.recipients_aliases = recipients_aliases;
|
||||
wti.remote_aliases = remote_aliases;
|
||||
prepare_wti(wti, get_block_height(b), get_block_datetime(b), in_tx, amount, td);
|
||||
WLT_LOG_L1("[MONEY SPENT]: " << epee::serialization::store_t_to_json(wti));
|
||||
rise_on_transfer2(wti);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::process_unconfirmed(const currency::transaction& tx, std::vector<std::string>& recipients, std::vector<std::string>& recipients_aliases)
|
||||
void wallet2::process_unconfirmed(const currency::transaction& tx, std::vector<std::string>& recipients, std::vector<std::string>& remote_aliases)
|
||||
{
|
||||
auto unconf_it = m_unconfirmed_txs.find(get_transaction_hash(tx));
|
||||
if (unconf_it != m_unconfirmed_txs.end())
|
||||
{
|
||||
wallet_public::wallet_transfer_info& wti = unconf_it->second;
|
||||
recipients = wti.remote_addresses;
|
||||
recipients_aliases = wti.recipients_aliases;
|
||||
remote_aliases = wti.remote_aliases;
|
||||
|
||||
m_unconfirmed_txs.erase(unconf_it);
|
||||
}
|
||||
|
|
@ -1473,7 +1489,7 @@ void wallet2::process_new_blockchain_entry(const currency::block& b, const curre
|
|||
|
||||
//optimization: seeking only for blocks that are not older then the wallet creation time plus 1 day. 1 day is for possible user incorrect time setup
|
||||
const std::vector<uint64_t>* pglobal_index = nullptr;
|
||||
if (b.timestamp + 60 * 60 * 24 > m_account.get_createtime())
|
||||
if (get_block_height(b) > get_wallet_minimum_height()) // b.timestamp + 60 * 60 * 24 > m_account.get_createtime())
|
||||
{
|
||||
pglobal_index = nullptr;
|
||||
if (bche.coinbase_ptr.get())
|
||||
|
|
@ -2650,6 +2666,19 @@ bool wallet2::check_connection()
|
|||
return m_core_proxy->check_connection();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::set_votes_config_path(const std::string& path_to_config_file/* = tools::get_default_data_dir() + "\voting_config.json"*/)
|
||||
{
|
||||
m_votes_config_path = path_to_config_file;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::load_votes_config()
|
||||
{
|
||||
if (boost::filesystem::exists(m_votes_config_path))
|
||||
{
|
||||
epee::serialization::load_t_from_json_file(m_votes_config, m_votes_config_path);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::load(const std::wstring& wallet_, const std::string& password)
|
||||
{
|
||||
clear();
|
||||
|
|
@ -2688,7 +2717,7 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password)
|
|||
{
|
||||
// old WALLET_FILE_BINARY_HEADER_VERSION version means no encryption
|
||||
need_to_resync = !tools::portable_unserialize_obj_from_stream(*this, data_file);
|
||||
WLT_LOG_L0("Detected format: WALLET_FILE_BINARY_HEADER_VERSION_INITAL(need_to_resync=" << need_to_resync << ")");
|
||||
WLT_LOG_L1("Detected format: WALLET_FILE_BINARY_HEADER_VERSION_INITAL (need_to_resync=" << need_to_resync << ")");
|
||||
}
|
||||
else if (wbh.m_ver == WALLET_FILE_BINARY_HEADER_VERSION_2)
|
||||
{
|
||||
|
|
@ -2697,7 +2726,7 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password)
|
|||
in.push(decrypt_filter);
|
||||
in.push(data_file);
|
||||
need_to_resync = !tools::portable_unserialize_obj_from_stream(*this, in);
|
||||
WLT_LOG_L0("Detected format: WALLET_FILE_BINARY_HEADER_VERSION_2(need_to_resync=" << need_to_resync << ")");
|
||||
WLT_LOG_L1("Detected format: WALLET_FILE_BINARY_HEADER_VERSION_2 (need_to_resync=" << need_to_resync << ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2718,10 +2747,11 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password)
|
|||
<< ", file_size=" << m_current_wallet_file_size
|
||||
<< ", blockchain_size: " << m_chain.get_blockchain_current_size()
|
||||
);
|
||||
WLT_LOG_L0("[LOADING]Blockchain shortener state: " << ENDL << m_chain.get_internal_state_text());
|
||||
WLT_LOG_L1("[LOADING]Blockchain shortener state: " << ENDL << m_chain.get_internal_state_text());
|
||||
|
||||
load_votes_config();
|
||||
|
||||
WLT_LOG_L0("(after loading: pending_key_images: " << m_pending_key_images.size() << ", pki file elements: " << m_pending_key_images_file_container.size() << ", tx_keys: " << m_tx_keys.size() << ")");
|
||||
WLT_LOG_L1("(after loading: pending_key_images: " << m_pending_key_images.size() << ", pki file elements: " << m_pending_key_images_file_container.size() << ", tx_keys: " << m_tx_keys.size() << ")");
|
||||
|
||||
if (need_to_resync)
|
||||
{
|
||||
|
|
@ -2793,7 +2823,7 @@ void wallet2::store(const std::wstring& path_to_save, const std::string& passwor
|
|||
boost::uintmax_t tmp_file_size = boost::filesystem::file_size(tmp_file_path);
|
||||
WLT_LOG_L0("Stored successfully to temporary file " << tmp_file_path.string() << ", file size=" << tmp_file_size);
|
||||
|
||||
WLT_LOG_L0("[LOADING]Blockchain shortener state: " << ENDL << m_chain.get_internal_state_text());
|
||||
WLT_LOG_L1("[LOADING]Blockchain shortener state: " << ENDL << m_chain.get_internal_state_text());
|
||||
|
||||
// for the sake of safety perform a double-renaming: wallet file -> old tmp, new tmp -> wallet file, remove old tmp
|
||||
|
||||
|
|
@ -3238,6 +3268,20 @@ bool enum_container(iterator_t it_begin, iterator_t it_end, callback_t cb)
|
|||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::is_consolidating_transaction(const wallet_public::wallet_transfer_info& wti)
|
||||
{
|
||||
if (!wti.is_income)
|
||||
{
|
||||
uint64_t income = 0;
|
||||
for (uint64_t r : wti.td.rcv){income += r;}
|
||||
uint64_t spend = 0;
|
||||
for (uint64_t s : wti.td.spn) { spend += s; }
|
||||
if (get_tx_fee(wti.tx) + income == spend)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::get_recent_transfers_history(std::vector<wallet_public::wallet_transfer_info>& trs, size_t offset, size_t count, uint64_t& total, uint64_t& last_item_index, bool exclude_mining_txs, bool start_from_end)
|
||||
{
|
||||
if (!count || offset >= m_transfer_history.size())
|
||||
|
|
@ -3247,7 +3291,7 @@ void wallet2::get_recent_transfers_history(std::vector<wallet_public::wallet_tra
|
|||
|
||||
if (exclude_mining_txs)
|
||||
{
|
||||
if (currency::is_coinbase(wti.tx))
|
||||
if (currency::is_coinbase(wti.tx) || is_consolidating_transaction(wti))
|
||||
return true;
|
||||
}
|
||||
trs.push_back(wti);
|
||||
|
|
@ -3255,6 +3299,11 @@ void wallet2::get_recent_transfers_history(std::vector<wallet_public::wallet_tra
|
|||
last_item_index = offset + local_offset;
|
||||
trs.back().transfer_internal_index = last_item_index;
|
||||
|
||||
if (wti.remote_addresses.size() == 1)
|
||||
{
|
||||
wti.remote_aliases = get_aliases_for_address(wti.remote_addresses[0]);
|
||||
}
|
||||
|
||||
if (trs.size() >= count)
|
||||
{
|
||||
return false;
|
||||
|
|
@ -3285,7 +3334,7 @@ void wallet2::wti_to_csv_entry(std::ostream& ss, const wallet_public::wallet_tra
|
|||
ss << wti.tx_blob_size << ",";
|
||||
ss << epee::string_tools::buff_to_hex_nodelimer(wti.payment_id) << ",";
|
||||
ss << "[";
|
||||
std::copy(wti.recipients_aliases.begin(), wti.recipients_aliases.end(), std::ostream_iterator<std::string>(ss, " "));
|
||||
std::copy(wti.remote_aliases.begin(), wti.remote_aliases.end(), std::ostream_iterator<std::string>(ss, " "));
|
||||
ss << "]" << ",";
|
||||
ss << (wti.is_income ? "in" : "out") << ",";
|
||||
ss << (wti.is_service ? "[SERVICE]" : "") << (wti.is_mixing ? "[MIXINS]" : "") << (wti.is_mining ? "[MINING]" : "") << ",";
|
||||
|
|
@ -3308,7 +3357,11 @@ void wallet2::wti_to_json_line(std::ostream& ss, const wallet_public::wallet_tra
|
|||
ss << epee::serialization::store_t_to_json(wti, 4) << ",";
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::set_connectivity_options(unsigned int timeout)
|
||||
{
|
||||
m_core_proxy->set_connectivity(timeout, WALLET_RCP_COUNT_ATTEMNTS);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::export_transaction_history(std::ostream& ss, const std::string& format, bool include_pos_transactions)
|
||||
{
|
||||
|
|
@ -3424,52 +3477,125 @@ bool wallet2::get_pos_entries(currency::COMMAND_RPC_SCAN_POS::request& req)
|
|||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_and_sign_pos_block(currency::block& b,
|
||||
const currency::pos_entry& pos_info,
|
||||
const crypto::public_key& source_tx_pub_key,
|
||||
uint64_t in_tx_output_index,
|
||||
const std::vector<const crypto::public_key*>& keys_ptrs)
|
||||
bool wallet2::prepare_and_sign_pos_block(const currency::pos_entry& pe, currency::block& b)
|
||||
{
|
||||
//generate coinbase transaction
|
||||
WLT_CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(currency::txin_gen), false, "Wrong output input in transaction");
|
||||
WLT_CHECK_AND_ASSERT_MES(b.miner_tx.vin[1].type() == typeid(currency::txin_to_key), false, "Wrong output input in transaction");
|
||||
auto& txin = boost::get<currency::txin_to_key>(b.miner_tx.vin[1]);
|
||||
txin.k_image = pos_info.keyimage;
|
||||
WLT_CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1 && b.miner_tx.signatures[0].size() == txin.key_offsets.size(),
|
||||
false, "Wrong signatures amount in coinbase transacton");
|
||||
bool r = false;
|
||||
WLT_CHECK_AND_ASSERT_MES(pe.wallet_index < m_transfers.size(), false, "invalid pe.wallet_index: " << pe.wallet_index);
|
||||
const transfer_details& td = m_transfers[pe.wallet_index];
|
||||
const transaction& source_tx = td.m_ptx_wallet_info->m_tx;
|
||||
const crypto::public_key source_tx_pub_key = get_tx_pub_key_from_extra(source_tx);
|
||||
WLT_CHECK_AND_ASSERT_MES(td.m_internal_output_index < source_tx.vout.size(), false, "invalid td.m_internal_output_index: " << td.m_internal_output_index);
|
||||
const currency::tx_out& stake_out = source_tx.vout[td.m_internal_output_index];
|
||||
|
||||
// calculate stake_out_derivation and secret_x (derived ephemeral secret key)
|
||||
crypto::key_derivation stake_out_derivation = AUTO_VAL_INIT(stake_out_derivation);
|
||||
r = crypto::generate_key_derivation(source_tx_pub_key, m_account.get_keys().view_secret_key, stake_out_derivation); // d = 8 * v * R
|
||||
WLT_CHECK_AND_ASSERT_MES(r, false, "generate_key_derivation failed, tid: " << pe.wallet_index << ", source_tx: " << get_transaction_hash(source_tx));
|
||||
crypto::secret_key secret_x = AUTO_VAL_INIT(secret_x);
|
||||
crypto::derive_secret_key(stake_out_derivation, td.m_internal_output_index, m_account.get_keys().spend_secret_key, secret_x); // x = Hs(8 * v * R, i) + s
|
||||
|
||||
WLT_CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(currency::txin_gen), false, "Wrong input 0 type in transaction: " << b.miner_tx.vin[0].type().name());
|
||||
WLT_CHECK_AND_ASSERT_MES(b.miner_tx.vin[1].type() == typeid(currency::txin_to_key), false, "Wrong input 1 type in transaction: " << b.miner_tx.vin[1].type().name());
|
||||
WLT_CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1, false, "Wrong sig prepared in PoS block");
|
||||
WLT_CHECK_AND_ASSERT_MES(stake_out.target.type() == typeid(currency::txout_to_key), false, "wrong type_id in source transaction in coinbase tx");
|
||||
|
||||
std::vector<crypto::signature>& sig = b.miner_tx.signatures[0];
|
||||
txin_to_key& stake_input = boost::get<currency::txin_to_key>(b.miner_tx.vin[1]);
|
||||
const txout_to_key& stake_out_target = boost::get<txout_to_key>(stake_out.target);
|
||||
|
||||
// partially fill stake input
|
||||
stake_input.k_image = pe.keyimage;
|
||||
stake_input.amount = stake_out.amount;
|
||||
|
||||
|
||||
// get decoys outputs and construct miner tx
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response decoys_resp = AUTO_VAL_INIT(decoys_resp);
|
||||
std::vector<const crypto::public_key*> ring;
|
||||
uint64_t secret_index = 0; // index of the real stake output
|
||||
if (m_required_decoys_count > 0)
|
||||
{
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request decoys_req = AUTO_VAL_INIT(decoys_req);
|
||||
decoys_req.use_forced_mix_outs = false;
|
||||
decoys_req.outs_count = m_required_decoys_count + 1; // one more to be able to skip a decoy in case it hits the real output
|
||||
decoys_req.amounts.push_back(pe.amount); // request one batch of decoys
|
||||
|
||||
//derive secret key
|
||||
crypto::key_derivation pos_coin_derivation = AUTO_VAL_INIT(pos_coin_derivation);
|
||||
bool r = crypto::generate_key_derivation(source_tx_pub_key,
|
||||
m_account.get_keys().view_secret_key,
|
||||
pos_coin_derivation);
|
||||
r = m_core_proxy->call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS(decoys_req, decoys_resp);
|
||||
// TODO @#@# do we need these exceptions?
|
||||
THROW_IF_FALSE_WALLET_EX(r, error::no_connection_to_daemon, "getrandom_outs.bin");
|
||||
THROW_IF_FALSE_WALLET_EX(decoys_resp.status != API_RETURN_CODE_BUSY, error::daemon_busy, "getrandom_outs.bin");
|
||||
THROW_IF_FALSE_WALLET_EX(decoys_resp.status == API_RETURN_CODE_OK, error::get_random_outs_error, decoys_resp.status);
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(decoys_resp.outs.size() == 1, "got wrong number of decoys batches: " << decoys_resp.outs.size());
|
||||
|
||||
// we expect that less decoys can be returned than requested, we will use them all anyway
|
||||
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(decoys_resp.outs[0].outs.size() <= m_required_decoys_count + 1, "for PoS stake tx got greater decoys to mix than requested: " << decoys_resp.outs[0].outs.size() << " < " << m_required_decoys_count + 1);
|
||||
|
||||
WLT_CHECK_AND_ASSERT_MES(r, false, "internal error: pos coin base generator: failed to generate_key_derivation("
|
||||
<< source_tx_pub_key
|
||||
<< ", view secret key: " << m_account.get_keys().view_secret_key << ")");
|
||||
auto& ring_candidates = decoys_resp.outs[0].outs;
|
||||
ring_candidates.emplace_front(td.m_global_output_index, stake_out_target.key);
|
||||
|
||||
crypto::secret_key derived_secret_ephemeral_key = AUTO_VAL_INIT(derived_secret_ephemeral_key);
|
||||
crypto::derive_secret_key(pos_coin_derivation,
|
||||
in_tx_output_index,
|
||||
m_account.get_keys().spend_secret_key,
|
||||
derived_secret_ephemeral_key);
|
||||
std::unordered_set<uint64_t> used_gindices;
|
||||
size_t good_outs_count = 0;
|
||||
for(auto it = ring_candidates.begin(); it != ring_candidates.end(); )
|
||||
{
|
||||
if (used_gindices.count(it->global_amount_index) != 0)
|
||||
{
|
||||
it = ring_candidates.erase(it);
|
||||
continue;
|
||||
}
|
||||
used_gindices.insert(it->global_amount_index);
|
||||
if (++good_outs_count == m_required_decoys_count + 1)
|
||||
{
|
||||
ring_candidates.erase(++it, ring_candidates.end());
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
// won't assert that ring_candidates.size() == m_required_decoys_count + 1 here as we will use all the decoys anyway
|
||||
if (ring_candidates.size() < m_required_decoys_count + 1)
|
||||
LOG_PRINT_YELLOW("PoS: using " << ring_candidates.size() - 1 << " decoys for mining tx, while " << m_required_decoys_count << " are required", LOG_LEVEL_1);
|
||||
|
||||
ring_candidates.sort([](auto& l, auto& r){ return l.global_amount_index < r.global_amount_index; }); // sort them now (note absolute_output_offsets_to_relative() below)
|
||||
|
||||
uint64_t i = 0;
|
||||
for(auto& el : ring_candidates)
|
||||
{
|
||||
uint64_t gindex = el.global_amount_index;
|
||||
if (gindex == td.m_global_output_index)
|
||||
secret_index = i;
|
||||
++i;
|
||||
ring.emplace_back(&el.out_key);
|
||||
stake_input.key_offsets.push_back(el.global_amount_index);
|
||||
}
|
||||
stake_input.key_offsets = absolute_output_offsets_to_relative(stake_input.key_offsets);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no decoys, the ring consist of one element -- the real stake output
|
||||
ring.emplace_back(&stake_out_target.key);
|
||||
stake_input.key_offsets.push_back(td.m_global_output_index);
|
||||
}
|
||||
|
||||
// sign block actually in coinbase transaction
|
||||
crypto::hash block_hash = currency::get_block_hash(b);
|
||||
|
||||
crypto::generate_ring_signature(block_hash,
|
||||
txin.k_image,
|
||||
keys_ptrs,
|
||||
derived_secret_ephemeral_key,
|
||||
0,
|
||||
&b.miner_tx.signatures[0][0]);
|
||||
// generate sring signature
|
||||
sig.resize(ring.size());
|
||||
crypto::generate_ring_signature(block_hash, stake_input.k_image, ring, secret_x, secret_index, sig.data());
|
||||
|
||||
WLT_LOG_L4("GENERATED RING SIGNATURE: block_id " << block_hash
|
||||
<< "txin.k_image" << txin.k_image
|
||||
<< "key_ptr:" << *keys_ptrs[0]
|
||||
<< "signature:" << b.miner_tx.signatures[0][0]);
|
||||
if (epee::log_space::get_set_log_detalisation_level() >= LOG_LEVEL_4)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "GENERATED RING SIGNATURE for PoS block coinbase:" << ENDL <<
|
||||
" block hash: " << block_hash << ENDL <<
|
||||
" key image: " << stake_input.k_image << ENDL <<
|
||||
" ring:" << ENDL;
|
||||
for(auto el: ring)
|
||||
ss << " " << *el << ENDL;
|
||||
ss << " signature:" << ENDL;
|
||||
for(auto el: sig)
|
||||
ss << " " << el << ENDL;
|
||||
WLT_LOG_L4(ss.str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3523,7 +3649,7 @@ bool wallet2::try_mint_pos(const currency::account_public_address& miner_address
|
|||
{
|
||||
TIME_MEASURE_START_MS(mining_duration_ms);
|
||||
mining_context ctx = AUTO_VAL_INIT(ctx);
|
||||
WLT_LOG_L1("Starting PoS mining iteration");
|
||||
WLT_LOG_L2("Starting PoS mining iteration");
|
||||
fill_mining_context(ctx);
|
||||
if (!ctx.rsp.is_pos_allowed)
|
||||
{
|
||||
|
|
@ -3531,6 +3657,10 @@ bool wallet2::try_mint_pos(const currency::account_public_address& miner_address
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
get_extra_text_for_block(m_last_pow_block_h);
|
||||
#endif
|
||||
|
||||
uint64_t pos_entries_amount = 0;
|
||||
for (auto& ent : ctx.sp.pos_entries)
|
||||
pos_entries_amount += ent.amount;
|
||||
|
|
@ -3576,7 +3706,31 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request&
|
|||
{
|
||||
return build_minted_block(req, rsp, m_account.get_public_address(), new_block_expected_height);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
std::string wallet2::get_extra_text_for_block(uint64_t new_block_expected_height)
|
||||
{
|
||||
size_t entries_voted = 0;
|
||||
std::string extra_text = "{";
|
||||
for (const auto& e : m_votes_config.entries)
|
||||
{
|
||||
if (e.h_start <= new_block_expected_height && e.h_end >= new_block_expected_height)
|
||||
{
|
||||
//do vote for/against this
|
||||
if (entries_voted != 0)
|
||||
extra_text += ",";
|
||||
extra_text += "\"";
|
||||
extra_text += e.proposal_id;
|
||||
extra_text += "\":";
|
||||
extra_text += e.vote ? "1" : "0";
|
||||
entries_voted++;
|
||||
}
|
||||
}
|
||||
extra_text += "}";
|
||||
if (!entries_voted)
|
||||
extra_text = "";
|
||||
return extra_text;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request& req,
|
||||
const currency::COMMAND_RPC_SCAN_POS::response& rsp,
|
||||
const currency::account_public_address& miner_address,
|
||||
|
|
@ -3586,19 +3740,20 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request&
|
|||
WLT_LOG_GREEN("Found kernel, constructing block", LOG_LEVEL_0);
|
||||
|
||||
CHECK_AND_NO_ASSERT_MES(rsp.index < req.pos_entries.size(), false, "call_COMMAND_RPC_SCAN_POS returned wrong index: " << rsp.index << ", expected less then " << req.pos_entries.size());
|
||||
const pos_entry& pe = req.pos_entries[rsp.index];
|
||||
|
||||
currency::COMMAND_RPC_GETBLOCKTEMPLATE::request tmpl_req = AUTO_VAL_INIT(tmpl_req);
|
||||
currency::COMMAND_RPC_GETBLOCKTEMPLATE::response tmpl_rsp = AUTO_VAL_INIT(tmpl_rsp);
|
||||
tmpl_req.wallet_address = get_account_address_as_str(miner_address);
|
||||
tmpl_req.stakeholder_address = get_account_address_as_str(m_account.get_public_address());
|
||||
tmpl_req.pos_block = true;
|
||||
tmpl_req.pos_amount = req.pos_entries[rsp.index].amount;
|
||||
tmpl_req.pos_index = req.pos_entries[rsp.index].index;
|
||||
tmpl_req.extra_text = m_miner_text_info;
|
||||
tmpl_req.stake_unlock_time = req.pos_entries[rsp.index].stake_unlock_time;
|
||||
tmpl_req.pos_amount = pe.amount;
|
||||
tmpl_req.pos_index = pe.index;
|
||||
tmpl_req.extra_text = get_extra_text_for_block(m_chain.get_top_block_height()); // m_miner_text_info;
|
||||
tmpl_req.stake_unlock_time = pe.stake_unlock_time;
|
||||
|
||||
// mark stake source as spent and make sure it will be restored in case of error
|
||||
const std::vector<uint64_t> stake_transfer_idx_vec{ req.pos_entries[rsp.index].wallet_index };
|
||||
const std::vector<uint64_t> stake_transfer_idx_vec{ pe.wallet_index };
|
||||
mark_transfers_as_spent(stake_transfer_idx_vec, "stake source");
|
||||
bool gracefull_leaving = false;
|
||||
auto stake_transfer_spent_flag_restorer = epee::misc_utils::create_scope_leave_handler([&](){
|
||||
|
|
@ -3630,27 +3785,17 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request&
|
|||
}
|
||||
|
||||
std::vector<const crypto::public_key*> keys_ptrs;
|
||||
WLT_CHECK_AND_ASSERT_MES(req.pos_entries[rsp.index].wallet_index < m_transfers.size(),
|
||||
WLT_CHECK_AND_ASSERT_MES(pe.wallet_index < m_transfers.size(),
|
||||
false, "Wrong wallet_index at generating coinbase transacton");
|
||||
|
||||
const auto& target = m_transfers[req.pos_entries[rsp.index].wallet_index].m_ptx_wallet_info->m_tx.vout[m_transfers[req.pos_entries[rsp.index].wallet_index].m_internal_output_index].target;
|
||||
WLT_CHECK_AND_ASSERT_MES(target.type() == typeid(currency::txout_to_key), false, "wrong type_id in source transaction in coinbase tx");
|
||||
|
||||
const currency::txout_to_key& txtokey = boost::get<currency::txout_to_key>(target);
|
||||
keys_ptrs.push_back(&txtokey.key);
|
||||
|
||||
// set a real timestamp
|
||||
b.timestamp = rsp.block_timestamp;
|
||||
uint64_t current_timestamp = m_core_runtime_config.get_core_time();
|
||||
set_block_datetime(current_timestamp, b);
|
||||
WLT_LOG_MAGENTA("Applying actual timestamp: " << current_timestamp, LOG_LEVEL_0);
|
||||
WLT_LOG_MAGENTA("Applying actual timestamp: " << current_timestamp, LOG_LEVEL_2);
|
||||
|
||||
//sign block
|
||||
res = prepare_and_sign_pos_block(b,
|
||||
req.pos_entries[rsp.index],
|
||||
get_tx_pub_key_from_extra(m_transfers[req.pos_entries[rsp.index].wallet_index].m_ptx_wallet_info->m_tx),
|
||||
m_transfers[req.pos_entries[rsp.index].wallet_index].m_internal_output_index,
|
||||
keys_ptrs);
|
||||
res = prepare_and_sign_pos_block(pe, b);
|
||||
WLT_CHECK_AND_ASSERT_MES(res, false, "Failed to prepare_and_sign_pos_block");
|
||||
|
||||
WLT_LOG_GREEN("Block " << get_block_hash(b) << " @ " << get_block_height(b) << " has been constructed, sending to core...", LOG_LEVEL_0);
|
||||
|
|
@ -3812,13 +3957,56 @@ void wallet2::push_alias_info_to_extra_according_to_hf_status(const currency::ex
|
|||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::request_alias_registration(const currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward)
|
||||
uint64_t wallet2::get_alias_cost(const std::string& alias)
|
||||
{
|
||||
currency::COMMAND_RPC_GET_ALIAS_REWARD::request req = AUTO_VAL_INIT(req);
|
||||
currency::COMMAND_RPC_GET_ALIAS_REWARD::response rsp = AUTO_VAL_INIT(rsp);
|
||||
req.alias = alias;
|
||||
if (!m_core_proxy->call_COMMAND_RPC_GET_ALIAS_REWARD(req, rsp))
|
||||
{
|
||||
throw std::runtime_error(std::string("Failed to get alias cost"));
|
||||
}
|
||||
|
||||
return rsp.reward + rsp.reward / 10; //add 10% of price to be sure;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::request_alias_registration(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward, const crypto::secret_key& authority_key)
|
||||
{
|
||||
if (!validate_alias_name(ai.m_alias))
|
||||
{
|
||||
throw std::runtime_error(std::string("wrong alias characters: ") + ai.m_alias);
|
||||
}
|
||||
|
||||
if (ai.m_alias.size() < ALIAS_MINIMUM_PUBLIC_SHORT_NAME_ALLOWED)
|
||||
{
|
||||
if (authority_key == currency::null_skey)
|
||||
{
|
||||
throw std::runtime_error(std::string("Short aliases is not allowed without authority key: ") + ALIAS_SHORT_NAMES_VALIDATION_PUB_KEY);
|
||||
}
|
||||
crypto::public_key authority_pub = AUTO_VAL_INIT(authority_pub);
|
||||
bool r = crypto::secret_key_to_public_key(authority_key, authority_pub);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "Failed to generate pub key from secrete authority key");
|
||||
|
||||
if (string_tools::pod_to_hex(authority_pub) != ALIAS_SHORT_NAMES_VALIDATION_PUB_KEY)
|
||||
{
|
||||
throw std::runtime_error(std::string("Short aliases is not allowed to register by this authority key"));
|
||||
}
|
||||
r = currency::sign_extra_alias_entry(ai, authority_pub, authority_key);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "Failed to sign alias update");
|
||||
WLT_LOG_L2("Generated update alias info: " << ENDL
|
||||
<< "alias: " << ai.m_alias << ENDL
|
||||
<< "signature: " << currency::print_t_array(ai.m_sign) << ENDL
|
||||
<< "signed(owner) pub key: " << m_account.get_keys().account_address.spend_public_key << ENDL
|
||||
<< "to address: " << get_account_address_as_str(ai.m_address) << ENDL
|
||||
<< "sign_buff_hash: " << currency::get_sign_buff_hash_for_alias_update(ai)
|
||||
);
|
||||
}
|
||||
|
||||
if (!reward)
|
||||
{
|
||||
reward = get_alias_cost(ai.m_alias);
|
||||
}
|
||||
|
||||
std::vector<currency::tx_destination_entry> destinations;
|
||||
std::vector<currency::extra_v> extra;
|
||||
std::vector<currency::attachment_v> attachments;
|
||||
|
|
@ -5036,7 +5224,7 @@ void wallet2::add_sent_unconfirmed_tx(const currency::transaction& tx,
|
|||
//unconfirmed_wti.tx = tx;
|
||||
unconfirmed_wti.remote_addresses = recipients;
|
||||
for (auto addr : recipients)
|
||||
unconfirmed_wti.recipients_aliases.push_back(get_alias_for_address(addr));
|
||||
unconfirmed_wti.remote_aliases.push_back(get_alias_for_address(addr));
|
||||
unconfirmed_wti.is_income = false;
|
||||
unconfirmed_wti.selected_indicies = selected_indicies;
|
||||
/*TODO: add selected_indicies to read_money_transfer2_details_from_tx in case of performance problems*/
|
||||
|
|
@ -5054,16 +5242,29 @@ void wallet2::add_sent_unconfirmed_tx(const currency::transaction& tx,
|
|||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::get_alias_for_address(const std::string& addr)
|
||||
{
|
||||
std::vector<std::string> aliases = get_aliases_for_address(addr);
|
||||
if (aliases.size())
|
||||
return aliases.front();
|
||||
return "";
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::vector<std::string> wallet2::get_aliases_for_address(const std::string& addr)
|
||||
{
|
||||
PROFILE_FUNC("wallet2::get_alias_for_address");
|
||||
currency::COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request req = addr;
|
||||
currency::COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response res = AUTO_VAL_INIT(res);
|
||||
std::vector<std::string> aliases;
|
||||
if (!m_core_proxy->call_COMMAND_RPC_GET_ALIASES_BY_ADDRESS(req, res))
|
||||
{
|
||||
WLT_LOG_L0("Failed to COMMAND_RPC_GET_ALIASES_BY_ADDRESS");
|
||||
return "";
|
||||
return aliases;
|
||||
}
|
||||
return res.alias_info.alias;
|
||||
for (auto& e : res.alias_info_list)
|
||||
{
|
||||
aliases.push_back(e.alias);
|
||||
}
|
||||
return aliases;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::transfer(const std::vector<currency::tx_destination_entry>& dsts, size_t fake_outputs_count,
|
||||
|
|
|
|||
|
|
@ -512,6 +512,7 @@ namespace tools
|
|||
const currency::account_base& get_account() const { return m_account; }
|
||||
|
||||
void get_recent_transfers_history(std::vector<wallet_public::wallet_transfer_info>& trs, size_t offset, size_t count, uint64_t& total, uint64_t& last_item_index, bool exclude_mining_txs = false, bool start_from_end = true);
|
||||
bool is_consolidating_transaction(const wallet_public::wallet_transfer_info& wti);
|
||||
uint64_t get_recent_transfers_total_count();
|
||||
uint64_t get_transfer_entries_count();
|
||||
void get_unconfirmed_transfers(std::vector<wallet_public::wallet_transfer_info>& trs, bool exclude_mining_txs = false);
|
||||
|
|
@ -538,13 +539,13 @@ namespace tools
|
|||
void push_offer(const bc_services::offer_details_ex& od, currency::transaction& res_tx);
|
||||
void cancel_offer_by_id(const crypto::hash& tx_id, uint64_t of_ind, uint64_t fee, currency::transaction& tx);
|
||||
void update_offer_by_id(const crypto::hash& tx_id, uint64_t of_ind, const bc_services::offer_details_ex& od, currency::transaction& res_tx);
|
||||
void request_alias_registration(const currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward);
|
||||
void request_alias_registration(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward, const crypto::secret_key& authority_key = currency::null_skey);
|
||||
void request_alias_update(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward);
|
||||
bool check_available_sources(std::list<uint64_t>& amounts);
|
||||
|
||||
bool check_available_sources(std::list<uint64_t>& amounts);
|
||||
|
||||
bool set_core_proxy(const std::shared_ptr<i_core_proxy>& proxy);
|
||||
void set_pos_mint_packing_size(uint64_t new_size);
|
||||
void set_pos_required_decoys_count(size_t v) { m_required_decoys_count = v; }
|
||||
void set_minimum_height(uint64_t h);
|
||||
std::shared_ptr<i_core_proxy> get_core_proxy();
|
||||
uint64_t balance() const;
|
||||
|
|
@ -802,11 +803,7 @@ namespace tools
|
|||
//next functions in public area only becausce of test_generator
|
||||
//TODO: Need refactoring - remove it back to private zone
|
||||
void set_genesis(const crypto::hash& genesis_hash);
|
||||
bool prepare_and_sign_pos_block(currency::block& b,
|
||||
const currency::pos_entry& pos_info,
|
||||
const crypto::public_key& source_tx_pub_key,
|
||||
uint64_t in_tx_output_index,
|
||||
const std::vector<const crypto::public_key*>& keys_ptrs);
|
||||
bool prepare_and_sign_pos_block(const currency::pos_entry& pe, currency::block& b);
|
||||
void process_new_blockchain_entry(const currency::block& b,
|
||||
const currency::block_direct_data_entry& bche,
|
||||
const crypto::hash& bl_id,
|
||||
|
|
@ -816,6 +813,7 @@ namespace tools
|
|||
bool get_pos_entries(currency::COMMAND_RPC_SCAN_POS::request& req);
|
||||
bool build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request& req, const currency::COMMAND_RPC_SCAN_POS::response& rsp, uint64_t new_block_expected_height = UINT64_MAX);
|
||||
bool build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request& req, const currency::COMMAND_RPC_SCAN_POS::response& rsp, const currency::account_public_address& miner_address, uint64_t new_block_expected_height = UINT64_MAX);
|
||||
std::string get_extra_text_for_block(uint64_t new_block_expected_height);
|
||||
bool reset_history();
|
||||
bool is_transfer_unlocked(const transfer_details& td) const;
|
||||
bool is_transfer_unlocked(const transfer_details& td, bool for_pos_mining, uint64_t& stake_lock_time) const;
|
||||
|
|
@ -864,8 +862,9 @@ namespace tools
|
|||
void set_use_deffered_global_outputs(bool use);
|
||||
construct_tx_param get_default_construct_tx_param_inital();
|
||||
void set_disable_tor_relay(bool disable);
|
||||
|
||||
uint64_t get_default_fee() {return TX_DEFAULT_FEE;}
|
||||
void export_transaction_history(std::ostream& ss, const std::string& format, bool include_pos_transactions = true);
|
||||
void set_connectivity_options(unsigned int timeout);
|
||||
|
||||
/*
|
||||
create_htlc_proposal: if htlc_hash == null_hash, then this wallet is originator of the atomic process, and
|
||||
|
|
@ -877,6 +876,9 @@ namespace tools
|
|||
void redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& origin, currency::transaction& result_tx);
|
||||
void redeem_htlc(const crypto::hash& htlc_tx_id, const std::string& origin);
|
||||
bool check_htlc_redeemed(const crypto::hash& htlc_tx_id, std::string& origin, crypto::hash& redeem_tx_id);
|
||||
|
||||
void set_votes_config_path(const std::string& path_to_config_file);
|
||||
const tools::wallet_public::wallet_vote_config& get_current_votes() { return m_votes_config; }
|
||||
private:
|
||||
|
||||
// -------- t_transport_state_notifier ------------------------------------------------
|
||||
|
|
@ -929,6 +931,7 @@ private:
|
|||
void handle_pulled_blocks(size_t& blocks_added, std::atomic<bool>& stop,
|
||||
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& blocks);
|
||||
std::string get_alias_for_address(const std::string& addr);
|
||||
std::vector<std::string> get_aliases_for_address(const std::string& addr);
|
||||
static bool build_kernel(const currency::pos_entry& pe, const currency::stake_modifier_type& stake_modifier, const uint64_t timestamp, currency::stake_kernel& kernel);
|
||||
bool is_connected_to_net();
|
||||
bool is_transfer_okay_for_pos(const transfer_details& tr, uint64_t& stake_unlock_time);
|
||||
|
|
@ -955,10 +958,9 @@ private:
|
|||
bool handle_cancel_proposal(wallet_public::wallet_transfer_info& wti, const bc_services::escrow_cancel_templates_body& ectb, const std::vector<currency::payload_items_v>& decrypted_attach);
|
||||
bool handle_expiration_list(uint64_t tx_expiration_ts_median);
|
||||
void handle_contract_expirations(uint64_t tx_expiration_ts_median);
|
||||
|
||||
void change_contract_state(wallet_public::escrow_contract_details_basic& contract, uint32_t new_state, const crypto::hash& contract_id, const wallet_public::wallet_transfer_info& wti) const;
|
||||
void change_contract_state(wallet_public::escrow_contract_details_basic& contract, uint32_t new_state, const crypto::hash& contract_id, const std::string& reason = "internal intention") const;
|
||||
|
||||
void load_votes_config();
|
||||
|
||||
const construct_tx_param& get_default_construct_tx_param();
|
||||
|
||||
|
|
@ -1014,6 +1016,7 @@ private:
|
|||
|
||||
void push_alias_info_to_extra_according_to_hf_status(const currency::extra_alias_entry& ai, std::vector<currency::extra_v>& extra);
|
||||
void remove_transfer_from_amount_gindex_map(uint64_t tid);
|
||||
uint64_t get_alias_cost(const std::string& alias);
|
||||
|
||||
static void wti_to_csv_entry(std::ostream& ss, const wallet_public::wallet_transfer_info& wti, size_t index);
|
||||
static void wti_to_txt_line(std::ostream& ss, const wallet_public::wallet_transfer_info& wti, size_t index);
|
||||
|
|
@ -1030,6 +1033,7 @@ private:
|
|||
std::atomic<uint64_t> m_last_bc_timestamp;
|
||||
bool m_do_rise_transfer;
|
||||
uint64_t m_pos_mint_packing_size;
|
||||
size_t m_required_decoys_count;
|
||||
|
||||
transfer_container m_transfers;
|
||||
multisig_transfer_container m_multisig_transfers;
|
||||
|
|
@ -1069,6 +1073,9 @@ private:
|
|||
mutable uint64_t m_current_wallet_file_size;
|
||||
bool m_use_deffered_global_outputs;
|
||||
bool m_disable_tor_relay;
|
||||
|
||||
std::string m_votes_config_path;
|
||||
tools::wallet_public::wallet_vote_config m_votes_config;
|
||||
//this needed to access wallets state in coretests, for creating abnormal blocks and tranmsactions
|
||||
friend class test_generator;
|
||||
|
||||
|
|
@ -1157,7 +1164,7 @@ namespace boost
|
|||
a & x.is_income;
|
||||
a & x.td;
|
||||
a & x.tx;
|
||||
a & x.recipients_aliases;
|
||||
a & x.remote_aliases;
|
||||
a & x.comment;
|
||||
a & x.contract;
|
||||
a & x.selected_indicies;
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ namespace wallet_public
|
|||
uint32_t tx_blob_size;
|
||||
std::string payment_id;
|
||||
std::vector<std::string> remote_addresses; //optional
|
||||
std::vector<std::string> recipients_aliases; //optional
|
||||
std::vector<std::string> remote_aliases; //optional, describe only if there only one remote address
|
||||
std::string comment;
|
||||
bool is_income;
|
||||
bool is_service;
|
||||
|
|
@ -127,7 +127,7 @@ namespace wallet_public
|
|||
KV_SERIALIZE(tx_blob_size)
|
||||
KV_SERIALIZE_BLOB_AS_HEX_STRING(payment_id)
|
||||
KV_SERIALIZE(remote_addresses)
|
||||
KV_SERIALIZE(recipients_aliases)
|
||||
KV_SERIALIZE(remote_aliases)
|
||||
KV_SERIALIZE(comment)
|
||||
KV_SERIALIZE(is_income)
|
||||
KV_SERIALIZE(timestamp)
|
||||
|
|
@ -377,7 +377,28 @@ namespace wallet_public
|
|||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_REGISTER_ALIAS
|
||||
{
|
||||
struct request
|
||||
{
|
||||
currency::alias_rpc_details al;
|
||||
crypto::secret_key authority_key;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(al)
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(authority_key)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
crypto::hash tx_id;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_POD_AS_HEX_STRING(tx_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct transfer_destination
|
||||
|
|
@ -1126,6 +1147,34 @@ namespace wallet_public
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct wallet_vote_config_entry
|
||||
{
|
||||
std::string proposal_id;
|
||||
uint64_t h_start;
|
||||
uint64_t h_end;
|
||||
bool vote;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(proposal_id)
|
||||
KV_SERIALIZE(h_start)
|
||||
KV_SERIALIZE(h_end)
|
||||
KV_SERIALIZE(vote)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
};
|
||||
|
||||
struct wallet_vote_config
|
||||
{
|
||||
std::vector<wallet_vote_config_entry> entries;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(entries)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
inline std::string get_escrow_contract_state_name(uint32_t state)
|
||||
{
|
||||
switch (state)
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ namespace tools
|
|||
static const uint64_t wallet_rpc_idle_work_period_ms = 2000;
|
||||
|
||||
m_do_mint = do_mint;
|
||||
if (m_do_mint)
|
||||
LOG_PRINT_CYAN("PoS mining is ON", LOG_LEVEL_0);
|
||||
|
||||
if (!offline_mode)
|
||||
{
|
||||
|
|
@ -143,6 +145,7 @@ namespace tools
|
|||
{
|
||||
m_wallet.set_miner_text_info(command_line::get_arg(vm, arg_miner_text_info));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
@ -747,6 +750,31 @@ namespace tools
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::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)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
currency::extra_alias_entry ai = AUTO_VAL_INIT(ai);
|
||||
if (!alias_rpc_details_to_alias_info(req.al, ai))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
|
||||
er.message = "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!currency::validate_alias_name(ai.m_alias))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
|
||||
er.message = "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS - Wrong alias name";
|
||||
return false;
|
||||
}
|
||||
|
||||
currency::transaction tx = AUTO_VAL_INIT(tx);
|
||||
m_wallet.request_alias_registration(ai, tx, m_wallet.get_default_fee(), 0, req.authority_key);
|
||||
res.tx_id = get_transaction_hash(tx);
|
||||
return true;
|
||||
WALLET_RPC_CATCH_TRY_ENTRY();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_contracts_send_proposal(const wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
WALLET_RPC_BEGIN_TRY_ENTRY();
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ namespace tools
|
|||
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)
|
||||
MAP_JON_RPC_WE("register_alias", on_register_alias, wallet_public::COMMAND_RPC_REGISTER_ALIAS)
|
||||
//contracts API
|
||||
MAP_JON_RPC_WE("contracts_send_proposal", on_contracts_send_proposal, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL)
|
||||
MAP_JON_RPC_WE("contracts_accept_proposal", on_contracts_accept_proposal, wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL)
|
||||
|
|
@ -93,6 +94,8 @@ namespace tools
|
|||
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_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);
|
||||
|
||||
|
||||
bool on_contracts_send_proposal(const wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_contracts_accept_proposal(const wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
|
|
|||
|
|
@ -956,6 +956,9 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st
|
|||
LOG_ERROR("Unexpected location reached");
|
||||
#endif
|
||||
}
|
||||
|
||||
w->set_votes_config_path(m_data_dir + "/" + CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME);
|
||||
|
||||
|
||||
std::string return_code = API_RETURN_CODE_OK;
|
||||
while (true)
|
||||
|
|
@ -970,6 +973,7 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st
|
|||
//w->get_unconfirmed_transfers(owr.recent_history.unconfirmed);
|
||||
w->get_unconfirmed_transfers(owr.recent_history.history, exclude_mining_txs);
|
||||
owr.wallet_local_bc_size = w->get_blockchain_current_size();
|
||||
|
||||
//workaround for missed fee
|
||||
//owr.seed = w->get_account().get_seed_phrase();
|
||||
break;
|
||||
|
|
@ -1061,6 +1065,7 @@ std::string wallets_manager::generate_wallet(const std::wstring& path, const std
|
|||
{
|
||||
std::shared_ptr<tools::wallet2> w(new tools::wallet2());
|
||||
w->set_use_deffered_global_outputs(m_use_deffered_global_outputs);
|
||||
w->set_votes_config_path(m_data_dir + "/" + CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME);
|
||||
owr.wallet_id = m_wallet_id_counter++;
|
||||
w->callback(std::shared_ptr<tools::i_wallet2_callback>(new i_wallet_to_i_backend_adapter(this, owr.wallet_id)));
|
||||
if (m_remote_node_mode)
|
||||
|
|
@ -1167,6 +1172,7 @@ std::string wallets_manager::restore_wallet(const std::wstring& path, const std:
|
|||
{
|
||||
std::shared_ptr<tools::wallet2> w(new tools::wallet2());
|
||||
w->set_use_deffered_global_outputs(m_use_deffered_global_outputs);
|
||||
w->set_votes_config_path(m_data_dir + "/" + CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME);
|
||||
owr.wallet_id = m_wallet_id_counter++;
|
||||
w->callback(std::shared_ptr<tools::i_wallet2_callback>(new i_wallet_to_i_backend_adapter(this, owr.wallet_id)));
|
||||
if (m_remote_node_mode)
|
||||
|
|
@ -1276,7 +1282,10 @@ std::string wallets_manager::get_alias_info_by_address(const std::string& addr,
|
|||
if (res.status != API_RETURN_CODE_OK)
|
||||
return res.status;
|
||||
|
||||
res_details = res.alias_info;
|
||||
if (res.alias_info_list.empty())
|
||||
return API_RETURN_CODE_NOT_FOUND;
|
||||
|
||||
res_details = res.alias_info_list.front();
|
||||
return res.status;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ target_link_libraries(coretests rpc wallet currency_core common crypto zlibstati
|
|||
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})
|
||||
target_link_libraries(performance_tests currency_core common crypto zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(performance_tests wallet currency_core common crypto zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(unit_tests wallet currency_core common crypto gtest_main zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(net_load_tests_clt currency_core common crypto gtest_main ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(net_load_tests_srv currency_core common crypto gtest_main ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ bool test_generator::sign_block(currency::block& b,
|
|||
|
||||
std::vector<const crypto::public_key*> keys_ptrs;
|
||||
keys_ptrs.push_back(&out_key);
|
||||
r = w.prepare_and_sign_pos_block(b, pe, source_tx_pub_key, out_i, keys_ptrs);
|
||||
r = w.prepare_and_sign_pos_block(pe, b);
|
||||
CHECK_AND_ASSERT_THROW_MES(r,"Failed to prepare_and_sign_pos_block()");
|
||||
|
||||
return true;
|
||||
|
|
@ -425,6 +425,8 @@ bool test_generator::build_wallets(const blockchain_vector& blocks,
|
|||
wallets.back()->assign_account(a);
|
||||
wallets.back()->get_account().set_createtime(0);
|
||||
wallets.back()->set_core_proxy(tmp_proxy);
|
||||
wallets.back()->set_minimum_height(0);
|
||||
wallets.back()->set_pos_required_decoys_count(0);
|
||||
|
||||
currency::core_runtime_config pc = cc;
|
||||
pc.min_coinstake_age = TESTS_POS_CONFIG_MIN_COINSTAKE_AGE;
|
||||
|
|
|
|||
|
|
@ -891,8 +891,9 @@ int main(int argc, char* argv[])
|
|||
// GENERATE_AND_PLAY(pos_wallet_minting_same_amount_diff_outs); // Long test! Takes ~10 hours to simulate 6000 blocks on 2015 middle-end computer
|
||||
//GENERATE_AND_PLAY(pos_emission_test); // Long test! by demand only
|
||||
GENERATE_AND_PLAY(pos_wallet_big_block_test);
|
||||
GENERATE_AND_PLAY(block_template_against_txs_size);
|
||||
//GENERATE_AND_PLAY(block_template_against_txs_size); // Long test! by demand only
|
||||
GENERATE_AND_PLAY(pos_altblocks_validation);
|
||||
GENERATE_AND_PLAY(pos_mining_with_decoys);
|
||||
|
||||
// alternative blocks and generic chain-switching tests
|
||||
GENERATE_AND_PLAY(gen_chain_switch_pow_pos);
|
||||
|
|
|
|||
|
|
@ -139,3 +139,121 @@ bool gen_pos_basic_tests::check_exchange_1(currency::core& c, size_t ev_index, c
|
|||
CHECK_EQ(offers.size(), 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
pos_mining_with_decoys::pos_mining_with_decoys()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(pos_mining_with_decoys, c1);
|
||||
}
|
||||
|
||||
bool pos_mining_with_decoys::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
currency::account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
|
||||
currency::account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
|
||||
currency::account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc.generate(); bob_acc.set_createtime(ts);
|
||||
currency::account_base& carol_acc = m_accounts[CAROL_ACC_IDX]; carol_acc.generate(); carol_acc.set_createtime(ts);
|
||||
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
|
||||
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
|
||||
REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1);
|
||||
|
||||
bool r = false;
|
||||
std::vector<tx_source_entry> sources;
|
||||
r = fill_tx_sources(sources, events, blk_0r, miner_acc.get_keys(), 2 * COIN, 0);
|
||||
CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources failed");
|
||||
std::vector<tx_destination_entry> destinations;
|
||||
destinations.emplace_back(47 * TESTS_DEFAULT_FEE, alice_acc.get_public_address());
|
||||
destinations.emplace_back(47 * TESTS_DEFAULT_FEE, miner_acc.get_public_address()); // as a decoy for Alice
|
||||
destinations.emplace_back(5 * TESTS_DEFAULT_FEE, bob_acc.get_public_address());
|
||||
destinations.emplace_back(COIN, carol_acc.get_public_address());
|
||||
|
||||
transaction tx_0{};
|
||||
r = construct_tx(miner_acc.get_keys(), sources, destinations, empty_attachment, tx_0, 0);
|
||||
CHECK_AND_ASSERT_MES(r, false, "construct_tx failed");
|
||||
events.push_back(tx_0);
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0);
|
||||
|
||||
REWIND_BLOCKS_N(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pos_mining_with_decoys::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
bool r = false;
|
||||
CHECK_AND_ASSERT_MES(!c.get_blockchain_storage().get_core_runtime_config().is_hardfork_active_for_height(4, c.get_top_block_height()), false, "HF4 should not be active");
|
||||
|
||||
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, m_accounts[MINER_ACC_IDX]);
|
||||
miner_wlt->refresh();
|
||||
|
||||
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]);
|
||||
alice_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", 47 * TESTS_DEFAULT_FEE, INVALID_BALANCE_VAL, 47 * TESTS_DEFAULT_FEE), false, "");
|
||||
|
||||
std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, m_accounts[BOB_ACC_IDX]);
|
||||
bob_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt, "Bob", 5 * TESTS_DEFAULT_FEE, INVALID_BALANCE_VAL, 5 * TESTS_DEFAULT_FEE), false, "");
|
||||
|
||||
std::shared_ptr<tools::wallet2> carol_wlt = init_playtime_test_wallet(events, c, m_accounts[CAROL_ACC_IDX]);
|
||||
carol_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*carol_wlt, "Carol", COIN, INVALID_BALANCE_VAL, COIN), false, "");
|
||||
|
||||
|
||||
// 1. Alice should be able to mine a PoS block with 1 decoys (ring size == 2)
|
||||
size_t top_block_height = c.get_top_block_height();
|
||||
|
||||
r = alice_wlt->try_mint_pos(m_accounts[ALICE_ACC_IDX].get_public_address());
|
||||
CHECK_AND_ASSERT_MES(r, false, "try_mint_pos failed");
|
||||
|
||||
{
|
||||
block b{};
|
||||
CHECK_AND_ASSERT_MES(c.get_blockchain_storage().get_top_block(b), false, "");
|
||||
CHECK_AND_ASSERT_MES(get_block_height(b) == top_block_height + 1, false, "unexpected top block height");
|
||||
|
||||
txin_to_key& intk = boost::get<txin_to_key>(b.miner_tx.vin[1]);
|
||||
CHECK_AND_ASSERT_MES(intk.amount == 47 * TESTS_DEFAULT_FEE, false, "incorrect amount: " << intk.amount);
|
||||
CHECK_AND_ASSERT_MES(intk.key_offsets.size() == 2, false, "unexpected ring size: " << intk.key_offsets.size());
|
||||
}
|
||||
|
||||
|
||||
// 2. Bob should only be able to mine a PoS block with zero decoys (ring size == 1)
|
||||
top_block_height = c.get_top_block_height();
|
||||
|
||||
r = bob_wlt->try_mint_pos(m_accounts[BOB_ACC_IDX].get_public_address());
|
||||
CHECK_AND_ASSERT_MES(r, false, "try_mint_pos failed");
|
||||
|
||||
{
|
||||
block b{};
|
||||
CHECK_AND_ASSERT_MES(c.get_blockchain_storage().get_top_block(b), false, "");
|
||||
CHECK_AND_ASSERT_MES(get_block_height(b) == top_block_height + 1, false, "unexpected top block height");
|
||||
|
||||
txin_to_key& intk = boost::get<txin_to_key>(b.miner_tx.vin[1]);
|
||||
CHECK_AND_ASSERT_MES(intk.amount == 5 * TESTS_DEFAULT_FEE, false, "incorrect amount: " << intk.amount);
|
||||
CHECK_AND_ASSERT_MES(intk.key_offsets.size() == 1, false, "unexpected ring size: " << intk.key_offsets.size());
|
||||
}
|
||||
|
||||
|
||||
// 3. Carol should only be able to mine a PoS block with CURRENCY_DEFAULT_DECOY_SET_SIZE decoys (ring size == CURRENCY_DEFAULT_DECOY_SET_SIZE + 1)
|
||||
top_block_height = c.get_top_block_height();
|
||||
|
||||
r = carol_wlt->try_mint_pos(m_accounts[CAROL_ACC_IDX].get_public_address());
|
||||
CHECK_AND_ASSERT_MES(r, false, "try_mint_pos failed");
|
||||
|
||||
{
|
||||
block b{};
|
||||
CHECK_AND_ASSERT_MES(c.get_blockchain_storage().get_top_block(b), false, "");
|
||||
CHECK_AND_ASSERT_MES(get_block_height(b) == top_block_height + 1, false, "unexpected top block height");
|
||||
|
||||
txin_to_key& intk = boost::get<txin_to_key>(b.miner_tx.vin[1]);
|
||||
CHECK_AND_ASSERT_MES(intk.amount == COIN, false, "incorrect amount: " << intk.amount);
|
||||
CHECK_AND_ASSERT_MES(intk.key_offsets.size() == CURRENCY_DEFAULT_DECOY_SET_SIZE + 1, false, "unexpected ring size: " << intk.key_offsets.size());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#pragma once
|
||||
#include "chaingen.h"
|
||||
#include "wallet_tests_basic.h"
|
||||
|
||||
struct gen_pos_basic_tests : public test_chain_unit_base
|
||||
{
|
||||
|
|
@ -22,3 +23,12 @@ struct gen_pos_basic_tests : public test_chain_unit_base
|
|||
bool check_exchange_1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct pos_mining_with_decoys : public wallet_test
|
||||
{
|
||||
pos_mining_with_decoys();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
bool configure_core(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1780,7 +1780,7 @@ bool gen_wallet_alias_via_special_wallet_funcs::c1(currency::core& c, size_t ev_
|
|||
uint64_t biggest_alias_reward = get_alias_coast_from_fee("a", TESTS_DEFAULT_FEE);
|
||||
std::shared_ptr<wlt_lambda_on_transfer2_wrapper> l(new wlt_lambda_on_transfer2_wrapper(
|
||||
[biggest_alias_reward](const tools::wallet_public::wallet_transfer_info& wti, uint64_t balance, uint64_t unlocked_balance, uint64_t total_mined) -> bool {
|
||||
return std::count(wti.recipients_aliases.begin(), wti.recipients_aliases.end(), "minerminer") == 1 &&
|
||||
return std::count(wti.remote_aliases.begin(), wti.remote_aliases.end(), "minerminer") == 1 &&
|
||||
wti.amount == biggest_alias_reward;
|
||||
}
|
||||
));
|
||||
|
|
|
|||
25
tests/performance_tests/api_test.cpp
Normal file
25
tests/performance_tests/api_test.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
#include "wallet/core_rpc_proxy.h"
|
||||
#include "wallet/core_default_rpc_proxy.h"
|
||||
|
||||
int test_get_rand_outs()
|
||||
{
|
||||
currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request req = AUTO_VAL_INIT(req);
|
||||
currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response rsp = AUTO_VAL_INIT(rsp);
|
||||
req.use_forced_mix_outs = false;
|
||||
req.outs_count = 10 + 1;
|
||||
for (size_t i = 0; i != 50; i++)
|
||||
req.amounts.push_back(COIN);
|
||||
|
||||
std::shared_ptr<tools::i_core_proxy> m_core_proxy(new tools::default_http_core_proxy());
|
||||
m_core_proxy->set_connection_addr("127.0.0.1:11211");
|
||||
m_core_proxy->check_connection();
|
||||
|
||||
bool r = m_core_proxy->call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS(req, rsp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
#include "htlc_hash_tests.h"
|
||||
#include "threads_pool_tests.h"
|
||||
|
||||
int test_get_rand_outs();
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
|
@ -36,7 +37,8 @@ int main(int argc, char** argv)
|
|||
epee::log_space::log_singletone::get_default_log_folder().c_str());
|
||||
|
||||
|
||||
thread_pool_tests();
|
||||
test_get_rand_outs();
|
||||
//thread_pool_tests();
|
||||
|
||||
// std::string buf1 = tools::get_varint_data<uint64_t>(CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX);
|
||||
// std::string buf2 = tools::get_varint_data<uint64_t>(CURRENCY_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX);
|
||||
|
|
|
|||
26
tests/unit_tests/votes_tests.cpp
Normal file
26
tests/unit_tests/votes_tests.cpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) 2012-2014 The Zano developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "misc_language.h"
|
||||
#include "currency_core/currency_format_utils.h"
|
||||
|
||||
|
||||
TEST(governance_testig, governance_tests_1)
|
||||
{
|
||||
std::string vote = "{\"ZGP11\":1,\"ZGP23\":0}";
|
||||
|
||||
std::list<std::pair<std::string, bool>> votes;
|
||||
currency::parse_vote(vote, votes);
|
||||
ASSERT_TRUE(votes.size() == 2);
|
||||
ASSERT_TRUE(votes.begin()->first == "ZGP11");
|
||||
ASSERT_TRUE(votes.begin()->second == true);
|
||||
ASSERT_TRUE((++votes.begin())->first == "ZGP23");
|
||||
ASSERT_TRUE((++votes.begin())->second == false);
|
||||
|
||||
}
|
||||
15
utils/boost_1.70_gcc_8.patch
Normal file
15
utils/boost_1.70_gcc_8.patch
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# This patch fixes compilation issue in Boost 1.70-1.71 while it is being compiled by GCC ver >= 8.3
|
||||
# -- sowle
|
||||
# see also: https://github.com/boostorg/thread/pull/297
|
||||
#
|
||||
--- boost/thread/pthread/thread_data.hpp.orig 2023-10-10 20:22:30.860192033 +0000
|
||||
+++ boost/thread/pthread/thread_data.hpp 2023-10-10 18:19:22.460764089 +0000
|
||||
@@ -57,7 +57,7 @@
|
||||
#else
|
||||
std::size_t page_size = ::sysconf( _SC_PAGESIZE);
|
||||
#endif
|
||||
-#if PTHREAD_STACK_MIN > 0
|
||||
+#ifdef PTHREAD_STACK_MIN
|
||||
if (size<PTHREAD_STACK_MIN) size=PTHREAD_STACK_MIN;
|
||||
#endif
|
||||
size = ((size+page_size-1)/page_size)*page_size;
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
call configure_local_paths.cmd
|
||||
|
||||
;; MSVC version-specific paths
|
||||
SET LOCAL_BOOST_LIB_PATH=%LOCAL_BOOST_PATH%\lib64-msvc-14.1
|
||||
SET QT_MSVC_PATH=%QT_PREFIX_PATH%\msvc2017_64
|
||||
|
||||
SET ACHIVE_NAME_PREFIX=zano-win-x64-
|
||||
|
|
@ -44,12 +43,13 @@ cd %SOURCES_PATH%
|
|||
rmdir build /s /q
|
||||
mkdir build
|
||||
cd build
|
||||
cmake %TESTNET_DEF% -D OPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" -D CMAKE_PREFIX_PATH="%QT_MSVC_PATH%" -D BUILD_GUI=TRUE -D STATIC=FALSE -G "Visual Studio 15 2017 Win64" -T host=x64 ..
|
||||
|
||||
cmake %TESTNET_DEF% -D OPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" -D CMAKE_PREFIX_PATH="%QT_MSVC_PATH%" -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.1" -G "Visual Studio 16 2019" -A x64 -T host=x64 ..
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
goto error
|
||||
)
|
||||
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvars64.bat" x86_amd64
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" x86_amd64
|
||||
echo on
|
||||
cd %SOURCES_PATH%\build
|
||||
|
||||
|
|
@ -96,7 +96,9 @@ del /F /Q %build_zip_path%
|
|||
|
||||
cd src\release
|
||||
|
||||
|
||||
call :sign_file Zano.exe || goto error
|
||||
call :sign_file zanod.exe || goto error
|
||||
call :sign_file simplewallet.exe || goto error
|
||||
|
||||
@echo on
|
||||
|
||||
|
|
@ -108,7 +110,7 @@ copy /Y zanod.exe bunch
|
|||
copy /Y simplewallet.exe bunch
|
||||
copy /Y *.pdb bunch
|
||||
|
||||
%QT_MSVC_PATH%\bin\windeployqt.exe bunch\Zano.exe
|
||||
%QT_MSVC_PATH%\bin\windeployqt.exe bunch\Zano.exe || goto error
|
||||
|
||||
cd bunch
|
||||
|
||||
|
|
@ -168,37 +170,31 @@ IF %ERRORLEVEL% NEQ 0 (
|
|||
set installer_file=%ACHIVE_NAME_PREFIX%%version%-installer.exe
|
||||
set installer_path=%BUILDS_PATH%\builds\%installer_file%
|
||||
|
||||
:: Signing temporary disable
|
||||
::@echo " SIGNING ...."
|
||||
::
|
||||
::%ZANO_SIGN_CMD% %installer_path%
|
||||
::IF %ERRORLEVEL% NEQ 0 (
|
||||
:: @echo "failed to sign installer"
|
||||
:: goto error
|
||||
::)
|
||||
@echo " SIGNING the installer ...."
|
||||
|
||||
call :sign_file %installer_path% || goto error
|
||||
|
||||
@echo " UPLOADING TO SERVER ...."
|
||||
|
||||
pscp %installer_path% zano_build_server:/var/www/html/builds
|
||||
pscp -load zano_build_server %installer_path% %ZANO_BUILDS_HOST%:/var/www/html/builds
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
@echo "FAILED TO UPLOAD EXE TO SERVER"
|
||||
goto error
|
||||
)
|
||||
call :sha256 %installer_path% installer_checksum
|
||||
|
||||
pscp %build_zip_path% zano_build_server:/var/www/html/builds
|
||||
pscp -load zano_build_server %build_zip_path% %ZANO_BUILDS_HOST%:/var/www/html/builds
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
@echo "FAILED TO UPLOAD ZIP TO SERVER"
|
||||
goto error
|
||||
)
|
||||
call :sha256 %build_zip_path% build_zip_checksum
|
||||
|
||||
set mail_msg="New %build_prefix% %TESTNET_LABEL%build for win-x64:<br>INST: <a href='https://build.zano.org/builds/%installer_file%'>https://build.zano.org/builds/%installer_file%</a> <br>sha256: %installer_checksum%<br><br>ZIP: <a href='https://build.zano.org/builds/%build_zip_filename%>https://build.zano.org/builds/%build_zip_filename%</a> <br>sha256: %build_zip_checksum%<br>"
|
||||
set mail_msg="New %build_prefix% %TESTNET_LABEL%build for win-x64:<br>INST: <a href='https://build.zano.org/builds/%installer_file%'>https://build.zano.org/builds/%installer_file%</a> <br>sha256: %installer_checksum%<br><br>ZIP: <a href='https://build.zano.org/builds/%build_zip_filename%'>https://build.zano.org/builds/%build_zip_filename%</a> <br>sha256: %build_zip_checksum%<br>"
|
||||
|
||||
echo %mail_msg%
|
||||
|
||||
senditquiet.exe -t %emails% -subject "Zano win-x64 %build_prefix% %TESTNET_LABEL%build %version%" -body %mail_msg%
|
||||
|
||||
python ../utils/build_mail.py "Zano win-x64 %build_prefix% %TESTNET_LABEL%build %version%" "%emails%" %mail_msg%
|
||||
|
||||
goto success
|
||||
|
||||
|
|
@ -228,3 +224,13 @@ EXIT /B %ERRORLEVEL%
|
|||
@set "%2=%hash: =%
|
||||
)
|
||||
@exit /B 0
|
||||
|
||||
|
||||
:sign_file
|
||||
@echo Signing %1...
|
||||
@call %ZANO_SIGN_CMD% %1
|
||||
@if %ERRORLEVEL% neq 0 (
|
||||
@echo ERROR: failed to sign %1
|
||||
@exit /B 1
|
||||
)
|
||||
@exit /B 0
|
||||
|
|
|
|||
13
utils/test_api_files/get_recent_txs_and_info.json
Normal file
13
utils/test_api_files/get_recent_txs_and_info.json
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 0,
|
||||
"method": "get_recent_txs_and_info",
|
||||
"params": {
|
||||
"offset": 0,
|
||||
"update_provision_info": true,
|
||||
"exclude_mining_txs": true,
|
||||
"count": 100,
|
||||
"order": "FROM_BEGIN_TO_END",
|
||||
"exclude_unconfirmed": true
|
||||
}
|
||||
}
|
||||
14
utils/test_api_files/register_alias.json
Normal file
14
utils/test_api_files/register_alias.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 0,
|
||||
"method": "register_alias",
|
||||
"params": {
|
||||
"al": {
|
||||
"alias": "zinazinazina",
|
||||
"address": "ZxDFNTq2Qf3FPvHakortVe3HxQBXwWNkWZydqfksgv9NRh1Z5b4tE91geYbmPn4JEoNxTMbj8Wj6R4v3fhV6K4Qh36hLacW1w",
|
||||
"tracking_key": "",
|
||||
"comment": ""
|
||||
},
|
||||
"authority_key": ""
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue