1
0
Fork 0
forked from lthn/blockchain

implemented governance initial code for wallet/daemon

This commit is contained in:
cryptozoidberg 2023-10-03 22:43:51 +02:00
parent 0ede461f25
commit 1886fae681
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
18 changed files with 309 additions and 12 deletions

View file

@ -77,8 +77,7 @@ namespace epee
bool insert_next_section(harray hSecArray, hsection& hinserted_childsection);
//------------------------------------------------------------------------
//delete entry (section, value or array)
bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr);
bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr);
//-------------------------------------------------------------------------------
bool store_to_binary(binarybuffer& target);
bool load_from_binary(const binarybuffer& target);
@ -87,6 +86,8 @@ namespace epee
bool dump_as_json(std::string& targetObj, size_t indent = 0, end_of_line_t eol = eol_crlf);
bool load_from_json(const std::string& source);
template<typename cb_t>
bool enum_entries(hsection hparent_section, cb_t cb);
private:
section m_root;
hsection get_root_section() {return &m_root;}
@ -384,6 +385,20 @@ namespace epee
CATCH_ENTRY("portable_storage::insert_first_value", nullptr);
}
//---------------------------------------------------------------------------------------------------------------
template<typename cb_t>
bool portable_storage::enum_entries(hsection hparent_section, cb_t cb)
{
TRY_ENTRY();
if (!hparent_section) hparent_section = &m_root;
for (const auto& e : hparent_section->m_entries)
{
if (!cb(e.first, e.second))
break;
}
return true;
CATCH_ENTRY("portable_storage::enum_entries", false);
}
template<class t_value>
bool portable_storage::insert_next_value(harray hval_array, const t_value& target)
{

View file

@ -37,6 +37,7 @@
#endif
#include <windows.h>
#endif
#include <cctype>
#include "warnings.h"
@ -310,7 +311,14 @@ namespace string_encoding
return get_md5_as_hexstring(src.data(), src.size());
}
#endif
inline
std::string toupper(std::string s)
{
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c) { return std::toupper(c); } // correct
);
return s;
}
}
}

View file

@ -2808,6 +2808,51 @@ size_t blockchain_storage::get_current_sequence_factor_for_alt(alt_chain_type& a
return n;
}
//------------------------------------------------------------------
bool blockchain_storage::get_pos_votes(uint64_t start_index, uint64_t end_index, vote_results& r)
{
CRITICAL_REGION_LOCAL(m_read_lock);
if (start_index >= m_db_blocks.size() || start_index >= end_index)
{
//LOG_PRINT_L0("Wrong starter or end index set: start_index = " << start_index << ", end_index=" << end_index << ", expected max index " << m_db_blocks.size() - 1);
return true;
}
std::map<std::string, vote_on_proposal> summary;
for (size_t i = start_index; i < m_db_blocks.size() && i < end_index; i++)
{
auto block_ptr = m_db_blocks[i];
//only coin holders can vote
if(!is_pos_block(block_ptr->bl))
continue;
r.total_pos_blocks++;
extra_user_data eud = AUTO_VAL_INIT(eud);
if (!get_type_in_variant_container(block_ptr->bl.miner_tx.extra, eud))
{
continue;
}
std::list<std::pair<std::string, bool>> votes;
if (!currency::parse_vote(eud.buff, votes))
{
continue;
}
for (const auto& v : votes)
{
if (v.second)
summary[v.first].vote_1++;
else
summary[v.first].vote_0++;
}
}
for (const auto s_entry : summary)
{
r.votes.push_back(s_entry.second);
r.votes.back().proposal_name = s_entry.first;
}
return true;
}
//------------------------------------------------------------------
std::string blockchain_storage::get_blockchain_string(uint64_t start_index, uint64_t end_index) const
{
std::stringstream ss;

View file

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

View file

@ -154,6 +154,28 @@ namespace currency
transactions_map onboard_transactions;
};
struct vote_on_proposal
{
std::string proposal_name;
uint64_t vote_1;
uint64_t vote_0;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(proposal_name)
KV_SERIALIZE(vote_1)
KV_SERIALIZE(vote_0)
END_KV_SERIALIZE_MAP()
};
struct vote_results
{
uint64_t total_pos_blocks; //total pos blocks in a given range
std::list<vote_on_proposal> votes;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(total_pos_blocks)
KV_SERIALIZE(votes)
END_KV_SERIALIZE_MAP()
};
}

View file

@ -214,6 +214,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

View file

@ -1615,6 +1615,35 @@ namespace currency
return timestamp;
}
//---------------------------------------------------------------
bool parse_vote(const std::string& json_, std::list<std::pair<std::string, bool>>& votes)
{
//do preliminary check of text if it looks like json
std::string::size_type pos = json_.find('{');
if (pos == std::string::npos)
return false;
std::string json = json_.substr(pos);
epee::serialization::portable_storage ps;
bool rs = ps.load_from_json(json);
if (!rs)
return false;
auto cb = [&](const std::string& name, const epee::serialization::storage_entry& entry) {
if (entry.type() == typeid(uint64_t))
{
bool vote = boost::get<uint64_t>(entry) ? true : false;
votes.push_back(std::make_pair(epee::string_encoding::toupper(name), vote));
}
return true;
};
ps.enum_entries(nullptr, cb);
return true;
}
//---------------------------------------------------------------
bool sign_multisig_input_in_tx(currency::transaction& tx, size_t ms_input_index, const currency::account_keys& keys, const currency::transaction& source_tx, bool *p_is_input_fully_signed /* = nullptr */)
{
#define LOC_CHK(cond, msg) CHECK_AND_ASSERT_MES(cond, false, msg << ", ms input index: " << ms_input_index << ", tx: " << get_transaction_hash(tx) << ", source tx: " << get_transaction_hash(source_tx))

View file

@ -362,7 +362,10 @@ namespace currency
bool fill_block_rpc_details(block_rpc_extended_info& pei_rpc, const block_extended_info& bei_chain, const crypto::hash& h);
void append_per_block_increments_for_tx(const transaction& tx, std::unordered_map<uint64_t, uint32_t>& gindices);
std::string get_word_from_timstamp(uint64_t timestamp, bool use_password);
uint64_t get_timstamp_from_word(std::string word, bool& password_used, const std::string& buff);
uint64_t get_timstamp_from_word(std::string word, bool& password_used);
bool parse_vote(const std::string& buff, std::list<std::pair<std::string, bool>>& votes);
std::string generate_origin_for_htlc(const txout_htlc& htlc, const account_keys& acc_keys);
template<class t_txin_v>
typename std::conditional<std::is_const<t_txin_v>::value, const std::vector<txin_etc_details_v>, std::vector<txin_etc_details_v> >::type& get_txin_etc_options(t_txin_v& in)

View file

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

View file

@ -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);
@ -150,6 +151,7 @@ namespace currency
MAP_JON_RPC ("get_pool_txs_brief_details", on_get_pool_txs_brief_details, COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS)
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 ("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)

View file

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

View file

@ -58,6 +58,7 @@ namespace
const command_line::arg_descriptor<std::string> arg_addr_to_compare ( "addr-to-compare", "");
const command_line::arg_descriptor<bool> arg_disable_tor_relay ( "disable-tor-relay", "Disable TOR relay", false);
const command_line::arg_descriptor<unsigned int> arg_set_timeout("set-timeout", "Set timeout for the wallet");
const command_line::arg_descriptor<std::string> arg_voting_config_file("voting-config-file", "Set voting config instead of getting if from daemon", "");
const command_line::arg_descriptor< std::vector<std::string> > arg_command ("command", "");
@ -413,6 +414,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()
@ -433,18 +435,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();
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)
{
@ -465,6 +470,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
{
@ -473,6 +481,7 @@ bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::st
// auditable watch-only aka tracking wallet
m_wallet->restore(epee::string_encoding::utf8_to_wstring(wallet_file), password, seed_or_tracking_seed, true, "");
message_writer(epee::log_space::console_color_white, true) << "Tracking wallet restored: " << m_wallet->get_account().get_public_address_str();
display_vote_info();
}
else
{
@ -509,11 +518,27 @@ bool simple_wallet::restore_wallet(const std::string& wallet_file, const std::st
return true;
}
//----------------------------------------------------------------------------------------------------
void simple_wallet::display_vote_info()
{
const wallet_vote_config& votes = m_wallet->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)
{
message_writer(epee::log_space::console_color_magenta, true) << "\t\t" << e.proposal_id << "\t\t" << (e.vote?"1":"0") << "\t\t("<< e.h_start << " - " << e.h_end <<")";
}
}
}
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)
{
@ -521,6 +546,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();
break;
}

View file

@ -96,6 +96,7 @@ namespace currency
uint64_t get_daemon_blockchain_height(std::string& err);
bool try_connect_to_daemon();
void display_vote_info();
//----------------- i_wallet2_callback ---------------------
virtual void on_new_block(uint64_t height, const currency::block& block) override;
@ -172,6 +173,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;

View file

@ -67,7 +67,8 @@ namespace tools
m_pos_mint_packing_size(WALLET_DEFAULT_POS_MINT_PACKING_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,7 +172,7 @@ std::shared_ptr<wallet2::transaction_wallet_info> wallet2::transform_value_to_pt
//----------------------------------------------------------------------------------------------------
void wallet2::init(const std::string& daemon_address)
{
m_miner_text_info = PROJECT_VERSION_LONG;
//m_miner_text_info = PROJECT_VERSION_LONG;
m_core_proxy->set_connection_addr(daemon_address);
m_core_proxy->check_connection();
}
@ -2650,6 +2651,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();
@ -2720,6 +2734,7 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password)
);
WLT_LOG_L1("[LOADING]Blockchain shortener state: " << ENDL << m_chain.get_internal_state_text());
load_votes_config();
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() << ")");
@ -3599,7 +3614,30 @@ 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++;
}
}
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,
@ -3617,7 +3655,7 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request&
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.extra_text = get_extra_text_for_block(new_block_expected_height); // m_miner_text_info;
tmpl_req.stake_unlock_time = req.pos_entries[rsp.index].stake_unlock_time;
// mark stake source as spent and make sure it will be restored in case of error

View file

@ -541,8 +541,7 @@ namespace tools
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(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward, const crypto::secret_key& authority_key = currency::null_skey);
void request_alias_update(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward);
bool check_available_sources(std::list<uint64_t>& amounts);
bool check_available_sources(std::list<uint64_t>& amounts);
bool set_core_proxy(const std::shared_ptr<i_core_proxy>& proxy);
void set_pos_mint_packing_size(uint64_t new_size);
@ -817,6 +816,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;
@ -879,6 +879,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 wallet_vote_config& get_current_votes() { return m_votes_config; }
private:
// -------- t_transport_state_notifier ------------------------------------------------
@ -958,10 +961,9 @@ private:
bool handle_cancel_proposal(wallet_public::wallet_transfer_info& wti, const bc_services::escrow_cancel_templates_body& ectb, const std::vector<currency::payload_items_v>& decrypted_attach);
bool handle_expiration_list(uint64_t tx_expiration_ts_median);
void handle_contract_expirations(uint64_t tx_expiration_ts_median);
void change_contract_state(wallet_public::escrow_contract_details_basic& contract, uint32_t new_state, const crypto::hash& contract_id, const wallet_public::wallet_transfer_info& wti) const;
void change_contract_state(wallet_public::escrow_contract_details_basic& contract, uint32_t new_state, const crypto::hash& contract_id, const std::string& reason = "internal intention") const;
void load_votes_config();
const construct_tx_param& get_default_construct_tx_param();
@ -1073,6 +1075,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;
wallet_vote_config m_votes_config;
//this needed to access wallets state in coretests, for creating abnormal blocks and tranmsactions
friend class test_generator;

View file

@ -1147,6 +1147,34 @@ namespace wallet_public
};
};
struct wallet_vote_config_entry
{
std::string proposal_id;
uint64_t h_start;
uint64_t h_end;
bool vote;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(proposal_id)
KV_SERIALIZE(h_start)
KV_SERIALIZE(h_end)
KV_SERIALIZE(vote)
END_KV_SERIALIZE_MAP()
};
struct wallet_vote_config
{
std::vector<wallet_vote_config_entry> entries;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(entries)
END_KV_SERIALIZE_MAP()
};
inline std::string get_escrow_contract_state_name(uint32_t state)
{
switch (state)

View file

@ -956,6 +956,9 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st
LOG_ERROR("Unexpected location reached");
#endif
}
w->set_votes_config_path(m_data_dir + "/" + CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME);
std::string return_code = API_RETURN_CODE_OK;
while (true)
@ -970,6 +973,7 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st
//w->get_unconfirmed_transfers(owr.recent_history.unconfirmed);
w->get_unconfirmed_transfers(owr.recent_history.history, exclude_mining_txs);
owr.wallet_local_bc_size = w->get_blockchain_current_size();
//workaround for missed fee
//owr.seed = w->get_account().get_seed_phrase();
break;
@ -1061,6 +1065,7 @@ std::string wallets_manager::generate_wallet(const std::wstring& path, const std
{
std::shared_ptr<tools::wallet2> w(new tools::wallet2());
w->set_use_deffered_global_outputs(m_use_deffered_global_outputs);
w->set_votes_config_path(m_data_dir + "/" + CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME);
owr.wallet_id = m_wallet_id_counter++;
w->callback(std::shared_ptr<tools::i_wallet2_callback>(new i_wallet_to_i_backend_adapter(this, owr.wallet_id)));
if (m_remote_node_mode)
@ -1167,6 +1172,7 @@ std::string wallets_manager::restore_wallet(const std::wstring& path, const std:
{
std::shared_ptr<tools::wallet2> w(new tools::wallet2());
w->set_use_deffered_global_outputs(m_use_deffered_global_outputs);
w->set_votes_config_path(m_data_dir + "/" + CURRENCY_VOTING_CONFIG_DEFAULT_FILENAME);
owr.wallet_id = m_wallet_id_counter++;
w->callback(std::shared_ptr<tools::i_wallet2_callback>(new i_wallet_to_i_backend_adapter(this, owr.wallet_id)));
if (m_remote_node_mode)

View file

@ -0,0 +1,26 @@
// Copyright (c) 2012-2014 The Zano developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "gtest/gtest.h"
#include <cstdint>
#include <vector>
#include "misc_language.h"
#include "currency_core/currency_format_utils.h"
TEST(governance_testig, governance_tests_1)
{
std::string vote = "{\"ZGP11\":1,\"ZGP23\":0}";
std::list<std::pair<std::string, bool>> votes;
currency::parse_vote(vote, votes);
ASSERT_TRUE(votes.size() == 2);
ASSERT_TRUE(votes.begin()->first == "ZGP11");
ASSERT_TRUE(votes.begin()->second == true);
ASSERT_TRUE((++votes.begin())->first == "ZGP23");
ASSERT_TRUE((++votes.begin())->second == false);
}