diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3f183c8e..913dcb72 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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()
diff --git a/README.md b/README.md
index 13558e5f..464c1410 100644
--- a/README.md
+++ b/README.md
@@ -13,13 +13,13 @@ Be sure to clone the repository properly:\
### Dependencies
| component / version | minimum
(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:
diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h
index 0b957a5f..7fc35112 100644
--- a/contrib/epee/include/misc_log_ex.h
+++ b/contrib/epee/include/misc_log_ex.h
@@ -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) { \
diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h
index c0b57596..e5f869b1 100644
--- a/contrib/epee/include/net/http_client.h
+++ b/contrib/epee/include/net/http_client.h
@@ -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
diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h
index 6b45950a..b3fca164 100644
--- a/contrib/epee/include/net/http_server_handlers_map2.h
+++ b/contrib/epee/include/net/http_server_handlers_map2.h
@@ -30,12 +30,20 @@
#include "storages/portable_storage_template_helper.h"
#include "http_base.h"
+
+
+template
+typename_t get_documentation_json_struct()
+{
+ return AUTO_VAL_INIT_T(typename_t);
+}
+
template
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();
+ response_t res = get_documentation_json_struct();
std::stringstream ss;
ss << prefix_name << ENDL
<< "REQUEST: " << ENDL << epee::serialization::store_t_to_json(req) << ENDL << "--------------------------------" << ENDL
diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h
index c02475c3..5d83353c 100644
--- a/contrib/epee/include/net/http_server_impl_base.h
+++ b/contrib/epee/include/net/http_server_impl_base.h
@@ -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;
}
diff --git a/contrib/epee/include/serialization/keyvalue_helpers.h b/contrib/epee/include/serialization/keyvalue_helpers.h
index 0ae911b0..79a4886b 100644
--- a/contrib/epee/include/serialization/keyvalue_helpers.h
+++ b/contrib/epee/include/serialization/keyvalue_helpers.h
@@ -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;
diff --git a/contrib/epee/include/storages/portable_storage.h b/contrib/epee/include/storages/portable_storage.h
index 4d36cc03..a5d46e19 100644
--- a/contrib/epee/include/storages/portable_storage.h
+++ b/contrib/epee/include/storages/portable_storage.h
@@ -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
+ 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
+ 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
bool portable_storage::insert_next_value(harray hval_array, const t_value& target)
{
diff --git a/contrib/epee/include/string_coding.h b/contrib/epee/include/string_coding.h
index 0b125bbd..a034dec9 100644
--- a/contrib/epee/include/string_coding.h
+++ b/contrib/epee/include/string_coding.h
@@ -37,6 +37,7 @@
#endif
#include
#endif
+#include
#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;
+ }
}
}
diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp
index dd22e385..00b46131 100644
--- a/src/currency_core/blockchain_storage.cpp
+++ b/src/currency_core/blockchain_storage.cpp
@@ -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 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> 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 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();
+}
+//------------------------------------------------------------------
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("760b85546678d2235a1843e18d8a016a2e4d9b8273cc4d7c09bebff1f6fa7eaf") )
- return true;
- if (alias == "test-420" && get_transaction_hash(tx) == epee::string_tools::parse_tpod_from_hex_string("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() << ")"
diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h
index cad2ca91..113cff0d 100644
--- a/src/currency_core/blockchain_storage.h
+++ b/src/currency_core/blockchain_storage.h
@@ -279,6 +279,7 @@ namespace currency
bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& 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 get_aliases_by_address(const account_public_address& addr)const;
template
bool enumerate_aliases(cb_t cb) const;
template
@@ -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;
diff --git a/src/currency_core/blockchain_storage_basic.h b/src/currency_core/blockchain_storage_basic.h
index 8a487003..6180968f 100644
--- a/src/currency_core/blockchain_storage_basic.h
+++ b/src/currency_core/blockchain_storage_basic.h
@@ -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 votes;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(total_pos_blocks)
+ KV_SERIALIZE(votes)
+ END_KV_SERIALIZE_MAP()
+ };
}
\ No newline at end of file
diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h
index 18e38c67..97e89eb4 100644
--- a/src/currency_core/currency_config.h
+++ b/src/currency_core/currency_config.h
@@ -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
diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp
index 7019ce41..15e130f3 100644
--- a/src/currency_core/currency_format_utils.cpp
+++ b/src/currency_core/currency_format_utils.cpp
@@ -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>& 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(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))
diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h
index 725b39e1..e8ecadcb 100644
--- a/src/currency_core/currency_format_utils.h
+++ b/src/currency_core/currency_format_utils.h
@@ -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& 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>& votes);
+
std::string generate_origin_for_htlc(const txout_htlc& htlc, const account_keys& acc_keys);
template
typename std::conditional::value, const std::vector, std::vector >::type& get_txin_etc_options(t_txin_v& in)
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 5adc60f9..0337952e 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -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 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;
}
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index 181dab35..6b7f08eb 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -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)
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 531cbe74..9ebe9c4e 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -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_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()
};
diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h
index b951a106..3fe31e72 100644
--- a/src/serialization/binary_archive.h
+++ b/src/serialization/binary_archive.h
@@ -51,7 +51,7 @@ template <>
struct binary_archive : public binary_archive_base
{
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);
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 1cc8d064..106c4bbf 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -49,14 +49,16 @@ namespace
const command_line::arg_descriptor arg_dont_refresh ( "no-refresh", "Do not refresh after load");
const command_line::arg_descriptor arg_dont_set_date ( "no-set-creation-date", "Do not set wallet creation date", false);
const command_line::arg_descriptor arg_daemon_port ("daemon-port", "Use daemon instance at port instead of default", 0);
- const command_line::arg_descriptor arg_log_level ("set-log", "");
+ //const command_line::arg_descriptor arg_log_level ("set-log", "");
const command_line::arg_descriptor arg_do_pos_mining ( "do-pos-mining", "Do PoS mining", false);
const command_line::arg_descriptor 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 arg_restore_wallet ( "restore-wallet", "Restore wallet from seed phrase or tracking seed and save it to ", "" );
const command_line::arg_descriptor arg_offline_mode ( "offline-mode", "Don't connect to daemon, work offline (for cold-signing process)");
const command_line::arg_descriptor arg_scan_for_wallet ( "scan-for-wallet", "");
const command_line::arg_descriptor arg_addr_to_compare ( "addr-to-compare", "");
- const command_line::arg_descriptor arg_disable_tor_relay ( "disable-tor-relay", "Do PoS mining", false);
+ const command_line::arg_descriptor arg_disable_tor_relay ( "disable-tor-relay", "Disable TOR relay", false);
+ const command_line::arg_descriptor arg_set_timeout("set-timeout", "Set timeout for the wallet");
+ const command_line::arg_descriptor arg_voting_config_file("voting-config-file", "Set voting config instead of getting if from daemon", "");
const command_line::arg_descriptor< std::vector > 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 - 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 &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());
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());
-
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& 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& 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& 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(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(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(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= along with --do-pos-mining to enable staking";
return EXIT_FAILURE;
}
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index f5138544..b7867d9a 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -59,6 +59,7 @@ namespace currency
bool dump_trunsfers(const std::vector& args);
bool dump_key_images(const std::vector& args);
bool show_incoming_transfers(const std::vector &args);
+ bool show_staking_history(const std::vector& args);
bool show_incoming_transfers_counts(const std::vector &args);
bool list_outputs(const std::vector &args);
bool show_payments(const std::vector &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;
diff --git a/src/version.h.in b/src/version.h.in
index 1afa6660..ba99b00a 100644
--- a/src/version.h.in
+++ b/src/version.h.in
@@ -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 "]"
diff --git a/src/wallet/core_default_rpc_proxy.cpp b/src/wallet/core_default_rpc_proxy.cpp
index 9de9f344..6fdbd693 100644
--- a/src/wallet/core_default_rpc_proxy.cpp
+++ b/src/wallet/core_default_rpc_proxy.cpp
@@ -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),
diff --git a/src/wallet/core_default_rpc_proxy.h b/src/wallet/core_default_rpc_proxy.h
index 77d3a4f3..d5773c4e 100644
--- a/src/wallet/core_default_rpc_proxy.h
+++ b/src/wallet/core_default_rpc_proxy.h
@@ -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 *plast_daemon_is_disconnected);
+ void set_plast_daemon_is_disconnected(std::atomic *plast_daemon_is_disconnected);
default_http_core_proxy();
private:
diff --git a/src/wallet/core_fast_rpc_proxy.h b/src/wallet/core_fast_rpc_proxy.h
index 9f1a1225..60035292 100644
--- a/src/wallet/core_fast_rpc_proxy.h
+++ b/src/wallet/core_fast_rpc_proxy.h
@@ -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
diff --git a/src/wallet/core_rpc_proxy.h b/src/wallet/core_rpc_proxy.h
index b8d2e303..68ff46b5 100644
--- a/src/wallet/core_rpc_proxy.h
+++ b/src/wallet/core_rpc_proxy.h
@@ -63,6 +63,7 @@ namespace tools
std::shared_ptr get_proxy_diagnostic_info() const { return m_pdiganostic_info; }
std::shared_ptr 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 m_pdiganostic_info;
};
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 9fe9323c..a4edf54c 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -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::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& proxy)
@@ -318,8 +334,8 @@ void wallet2::fetch_tx_global_indixes(const std::list* pglobal_indexes)
{
- std::vector recipients, recipients_aliases;
- process_unconfirmed(tx, recipients, recipients_aliases);
+ std::vector recipients, remote_aliases;
+ process_unconfirmed(tx, recipients, remote_aliases);
std::vector 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& recipients,
- const std::vector& recipients_aliases)
+ const std::vector& remote_aliases)
{
m_transfer_history.push_back(AUTO_VAL_INIT(wallet_public::wallet_transfer_info()));
wallet_public::wallet_transfer_info& wti = m_transfer_history.back();
wti.is_income = false;
wti.remote_addresses = recipients;
- wti.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& recipients, std::vector& recipients_aliases)
+void wallet2::process_unconfirmed(const currency::transaction& tx, std::vector& recipients, std::vector& 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* 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& 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= 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(ss, " "));
+ std::copy(wti.remote_aliases.begin(), wti.remote_aliases.end(), std::ostream_iterator(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& 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(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& sig = b.miner_tx.signatures[0];
+ txin_to_key& stake_input = boost::get(b.miner_tx.vin[1]);
+ const txout_to_key& stake_out_target = boost::get(stake_out.target);
+
+ // partially fill stake input
+ stake_input.k_image = pe.keyimage;
+ stake_input.amount = 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 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 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 stake_transfer_idx_vec{ req.pos_entries[rsp.index].wallet_index };
+ const std::vector 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 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(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 destinations;
std::vector extra;
std::vector 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 aliases = get_aliases_for_address(addr);
+ if (aliases.size())
+ return aliases.front();
+ return "";
+}
+//----------------------------------------------------------------------------------------------------
+std::vector 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 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& dsts, size_t fake_outputs_count,
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index d34cc4e0..694851f3 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -512,6 +512,7 @@ namespace tools
const currency::account_base& get_account() const { return m_account; }
void get_recent_transfers_history(std::vector& 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& 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& amounts);
-
+ bool check_available_sources(std::list& amounts);
bool set_core_proxy(const std::shared_ptr& 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 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& 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& stop,
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& blocks);
std::string get_alias_for_address(const std::string& addr);
+ std::vector 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& 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& 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 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;
diff --git a/src/wallet/wallet_public_structs_defs.h b/src/wallet/wallet_public_structs_defs.h
index ce318bf5..141f6e8f 100644
--- a/src/wallet/wallet_public_structs_defs.h
+++ b/src/wallet/wallet_public_structs_defs.h
@@ -97,7 +97,7 @@ namespace wallet_public
uint32_t tx_blob_size;
std::string payment_id;
std::vector remote_addresses; //optional
- std::vector recipients_aliases; //optional
+ std::vector 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 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)
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index dc809096..cff267a6 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -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();
diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h
index 8d1aa084..1edd325c 100644
--- a/src/wallet/wallet_rpc_server.h
+++ b/src/wallet/wallet_rpc_server.h
@@ -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);
diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp
index f19203c6..8b3bd2aa 100644
--- a/src/wallet/wallets_manager.cpp
+++ b/src/wallet/wallets_manager.cpp
@@ -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 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(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 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(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;
}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 5e6a9006..40c89aee 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -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})
diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp
index 4ec33355..f4e1fc4e 100644
--- a/tests/core_tests/chaingen.cpp
+++ b/tests/core_tests/chaingen.cpp
@@ -382,7 +382,7 @@ bool test_generator::sign_block(currency::block& b,
std::vector 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;
diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp
index d09d1558..e92e3f72 100644
--- a/tests/core_tests/chaingen_main.cpp
+++ b/tests/core_tests/chaingen_main.cpp
@@ -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);
diff --git a/tests/core_tests/pos_basic_tests.cpp b/tests/core_tests/pos_basic_tests.cpp
index 22b40f78..6bc00a5d 100644
--- a/tests/core_tests/pos_basic_tests.cpp
+++ b/tests/core_tests/pos_basic_tests.cpp
@@ -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& 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 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 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& 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 miner_wlt = init_playtime_test_wallet(events, c, m_accounts[MINER_ACC_IDX]);
+ miner_wlt->refresh();
+
+ std::shared_ptr 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 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 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(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(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(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;
+}
diff --git a/tests/core_tests/pos_basic_tests.h b/tests/core_tests/pos_basic_tests.h
index 6bdb5c45..bd4fbf10 100644
--- a/tests/core_tests/pos_basic_tests.h
+++ b/tests/core_tests/pos_basic_tests.h
@@ -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& events);
};
+
+
+struct pos_mining_with_decoys : public wallet_test
+{
+ pos_mining_with_decoys();
+ bool generate(std::vector& events) const;
+ bool configure_core(currency::core& c, size_t ev_index, const std::vector& events);
+ bool c1(currency::core& c, size_t ev_index, const std::vector& events);
+};
diff --git a/tests/core_tests/wallet_tests.cpp b/tests/core_tests/wallet_tests.cpp
index f4f2e027..5aaaf611 100644
--- a/tests/core_tests/wallet_tests.cpp
+++ b/tests/core_tests/wallet_tests.cpp
@@ -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 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;
}
));
diff --git a/tests/performance_tests/api_test.cpp b/tests/performance_tests/api_test.cpp
new file mode 100644
index 00000000..6a492c28
--- /dev/null
+++ b/tests/performance_tests/api_test.cpp
@@ -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 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;
+}
diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp
index e8d7a2ed..5472f68b 100644
--- a/tests/performance_tests/main.cpp
+++ b/tests/performance_tests/main.cpp
@@ -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(CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX);
// std::string buf2 = tools::get_varint_data(CURRENCY_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX);
diff --git a/tests/unit_tests/votes_tests.cpp b/tests/unit_tests/votes_tests.cpp
new file mode 100644
index 00000000..d6f0a90c
--- /dev/null
+++ b/tests/unit_tests/votes_tests.cpp
@@ -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
+#include
+
+#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> 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);
+
+}
\ No newline at end of file
diff --git a/utils/boost_1.70_gcc_8.patch b/utils/boost_1.70_gcc_8.patch
new file mode 100644
index 00000000..812eed14
--- /dev/null
+++ b/utils/boost_1.70_gcc_8.patch
@@ -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