1
0
Fork 0
forked from lthn/blockchain

Merge branch 'develop' into release

This commit is contained in:
sowle 2019-07-09 22:36:20 +03:00
commit 0ab50c8fa2
42 changed files with 10970 additions and 7350 deletions

View file

@ -64,6 +64,23 @@ namespace epee
epee::string_tools::hex_to_pod(a, res);
return res;
}
//basic helpers for blob-to-hex serialization
inline std::string transform_binbuf_to_hexstr(const std::string& a)
{
return epee::string_tools::buff_to_hex_nodelimer(a);
}
inline std::string transform_hexstr_to_binbuff(const std::string& a)
{
std::string res;
if (!epee::string_tools::parse_hexstr_to_binbuff(a, res))
{
CHECK_AND_ASSERT_THROW_MES(false, "Failed to parse hex string:" << a);
}
return res;
}
//-------------------------------------------------------------------------------------------------------------------

View file

@ -78,7 +78,8 @@ public: \
#define KV_SERIALIZE_POD_AS_HEX_STRING_N(varialble, val_name) \
KV_SERIALIZE_CUSTOM_N(varialble, std::string, epee::transform_t_pod_to_str<decltype(varialble)>, epee::transform_str_to_t_pod<decltype(varialble)>, val_name)
#define KV_SERIALIZE_BLOB_AS_HEX_STRING_N(varialble, val_name) \
KV_SERIALIZE_CUSTOM_N(varialble, std::string, epee::transform_binbuf_to_hexstr, epee::transform_hexstr_to_binbuff, val_name)
#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name) \
@ -99,6 +100,8 @@ public: \
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB(varialble) KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, #varialble)
#define KV_SERIALIZE_CUSTOM(varialble, stored_type, from_v_to_stored, from_stored_to_v) KV_SERIALIZE_CUSTOM_N(varialble, stored_type, from_v_to_stored, from_stored_to_v, #varialble)
#define KV_SERIALIZE_POD_AS_HEX_STRING(varialble) KV_SERIALIZE_POD_AS_HEX_STRING_N(varialble, #varialble)
#define KV_SERIALIZE_BLOB_AS_HEX_STRING(varialble) KV_SERIALIZE_BLOB_AS_HEX_STRING_N(varialble, #varialble)
#define KV_CHAIN_MAP(variable_obj) epee::namespace_accessor<decltype(this_ref.variable_obj)>::template serialize_map<is_store>(this_ref.variable_obj, stg, hparent_section);

View file

@ -28,4 +28,5 @@ namespace command_line
const arg_descriptor<bool> arg_disable_upnp = { "disable-upnp", "Disable UPnP (enhances local network privacy)", false, true };
const arg_descriptor<bool> arg_disable_stop_if_time_out_of_sync = { "disable-stop-if-time-out-of-sync", "Do not stop the daemon if serious time synchronization problem is detected", false, true };
const arg_descriptor<bool> arg_disable_stop_on_low_free_space = { "disable-stop-on-low-free-space", "Do not stop the daemon if free space at data dir is critically low", false, true };
}

View file

@ -186,4 +186,5 @@ namespace command_line
extern const arg_descriptor<bool> arg_show_rpc_autodoc;
extern const arg_descriptor<bool> arg_disable_upnp;
extern const arg_descriptor<bool> arg_disable_stop_if_time_out_of_sync;
extern const arg_descriptor<bool> arg_disable_stop_on_low_free_space;
}

View file

@ -58,6 +58,7 @@ namespace
const command_line::arg_descriptor<int64_t> arg_set_peer_log_level = { "set-peer-log-level", "Set log level for remote peer", 0, true };
const command_line::arg_descriptor<std::string> arg_download_peer_log = { "download-peer-log", "Download log from remote peer <starting_offset>[,<count>]", "", true };
const command_line::arg_descriptor<bool> arg_do_consloe_log = { "do-console-log", "Tool generates debug console output(debug purposes)", "", true };
const command_line::arg_descriptor<std::string> arg_generate_integrated_address = { "generate-integrated-address", "Tool create integrated address from simple address and payment_id", "", true };
}
typedef COMMAND_REQUEST_STAT_INFO_T<t_currency_protocol_handler<core>::stat_info> COMMAND_REQUEST_STAT_INFO;
@ -1035,6 +1036,48 @@ bool handle_download_peer_log(po::variables_map& vm)
return true;
}
bool handle_generate_integrated_address(po::variables_map& vm)
{
std::string add_and_payment_id = command_line::get_arg(vm, arg_generate_integrated_address);
std::string::size_type off = add_and_payment_id.find(':');
if (off == std::string::npos)
{
std::cout << "ERROR: wrong syntax, delimiter symbol (':') not found " << ENDL;
return false;
}
std::string address = add_and_payment_id.substr(0, off);
std::string payment_id = add_and_payment_id.substr(off+1, add_and_payment_id.length());
std::string payment_id_bin;
if (!epee::string_tools::parse_hexstr_to_binbuff(payment_id, payment_id_bin))
{
payment_id_bin = payment_id;
}
if (address.empty() || payment_id_bin.empty())
{
std::cout << "ERROR: wrong syntax, address or paymentd_id not set" << ENDL;
return false;
}
account_public_address acc_addr = AUTO_VAL_INIT(acc_addr);
bool r = currency::get_account_address_from_str(acc_addr, address);
if (!r)
{
std::cout << "ERROR: wrong syntax, address is wrong: " << address << ENDL;
return false;
}
std::string integrated_addr = currency::get_account_address_and_payment_id_as_str(acc_addr, payment_id_bin);
std::cout << "Integrated address: " << integrated_addr << ENDL;
return true;
}
//---------------------------------------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
@ -1076,6 +1119,9 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_set_peer_log_level);
command_line::add_arg(desc_params, arg_download_peer_log);
command_line::add_arg(desc_params, arg_do_consloe_log);
command_line::add_arg(desc_params, arg_generate_integrated_address);
po::options_description desc_all;
desc_all.add(desc_general).add(desc_params);
@ -1144,6 +1190,10 @@ int main(int argc, char* argv[])
{
return handle_download_peer_log(vm) ? EXIT_SUCCESS : EXIT_FAILURE;
}
else if (command_line::has_arg(vm, arg_generate_integrated_address))
{
return handle_generate_integrated_address(vm) ? EXIT_SUCCESS : EXIT_FAILURE;
}
else
{
std::cerr << "Not enough arguments." << ENDL;

View file

@ -304,6 +304,10 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
if(!m_db_blocks.back()->bl.timestamp)
timestamp_diff = m_core_runtime_config.get_core_time() - 1341378000;
m_db.begin_transaction();
set_lost_tx_unmixable();
m_db.commit_transaction();
LOG_PRINT_GREEN("Blockchain initialized. (v:" << m_db_storage_major_compatibility_version << ") last block: " << m_db_blocks.size() - 1 << ENDL
<< "genesis: " << get_block_hash(m_db_blocks[0]->bl) << ENDL
<< "last block: " << m_db_blocks.size() - 1 << ", " << misc_utils::get_time_interval_string(timestamp_diff) << " time ago" << ENDL
@ -311,10 +315,49 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
<< "current pow difficulty: " << get_next_diff_conditional(false) << ENDL
<< "total transactions: " << m_db_transactions.size(),
LOG_LEVEL_0);
return true;
}
//------------------------------------------------------------------
bool blockchain_storage::set_lost_tx_unmixable_for_height(uint64_t height)
{
if (height == 75738)
return set_lost_tx_unmixable();
return true;
}
//------------------------------------------------------------------
bool blockchain_storage::set_lost_tx_unmixable()
{
if (m_db_blocks.size() > 75738)
{
crypto::hash tx_id_1 = epee::string_tools::parse_tpod_from_hex_string<crypto::hash>("c2a2229d614e7c026433efbcfdbd0be1f68d9b419220336df3e2c209f5d57314");
crypto::hash tx_id_2 = epee::string_tools::parse_tpod_from_hex_string<crypto::hash>("647f936c6ffbd136f5c95d9a90ad554bdb4c01541c6eb5755ad40b984d80da67");
auto tx_ptr_1 = m_db_transactions.find(tx_id_1);
CHECK_AND_ASSERT_MES(tx_ptr_1, false, "Internal error: filed to find lost tx");
transaction_chain_entry tx1_local_entry(*tx_ptr_1);
for (size_t i = 0; i != tx1_local_entry.m_spent_flags.size(); i++)
{
tx1_local_entry.m_spent_flags[i] = true;
}
m_db_transactions.set(tx_id_1, tx1_local_entry);
auto tx_ptr_2 = m_db_transactions.find(tx_id_2);
transaction_chain_entry tx2_local_entry(*tx_ptr_2);
CHECK_AND_ASSERT_MES(tx_ptr_1, false, "Internal error: filed to find lost tx");
for (size_t i = 0; i != tx2_local_entry.m_spent_flags.size(); i++)
{
tx2_local_entry.m_spent_flags[i] = true;
}
m_db_transactions.set(tx_id_2, tx2_local_entry);
}
return true;
}
//------------------------------------------------------------------
void blockchain_storage::patch_out_if_needed(txout_to_key& out, const crypto::hash& tx_id, uint64_t n) const
{
}
//------------------------------------------------------------------
void blockchain_storage::initialize_db_solo_options_values()
{
@ -1578,7 +1621,19 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
{
//block orphaned
bvc.m_marked_as_orphaned = true;
LOG_PRINT_RED_L0("Block recognized as orphaned and rejected, id = " << id << "," << ENDL << "parent id = " << b.prev_id << ENDL << "height = " << coinbase_height);
if (m_invalid_blocks.count(id) != 0)
{
LOG_PRINT_RED_L0("Block recognized as blacklisted and rejected, id = " << id << "," << ENDL << "parent id = " << b.prev_id << ENDL << "height = " << coinbase_height);
}
else if (m_invalid_blocks.count(b.prev_id) != 0)
{
LOG_PRINT_RED_L0("Block recognized as orphaned (parent " << b.prev_id << " is in blacklist) and rejected, id = " << id << "," << ENDL << "parent id = " << b.prev_id << ENDL << "height = " << coinbase_height);
}
else
{
LOG_PRINT_RED_L0("Block recognized as orphaned and rejected, id = " << id << "," << ENDL << "parent id = " << b.prev_id << ENDL << "height = " << coinbase_height);
}
}
CHECK_AND_ASSERT_MES(validate_blockchain_prev_links(), false, "EPIC FAIL!");
@ -3406,8 +3461,7 @@ uint64_t blockchain_storage::tx_fee_median_for_height(uint64_t h)const
//------------------------------------------------------------------
bool blockchain_storage::validate_all_aliases_for_new_median_mode()
{
LOG_PRINT_L0("Started reinitialization of median fee...");
LOG_PRINT_L0("Started reinitialization of median fee...");
math_helper::once_a_time_seconds<10> log_idle;
uint64_t sz = m_db_blocks.size();
for (uint64_t i = 0; i != sz; i++)
@ -3446,6 +3500,80 @@ bool blockchain_storage::validate_all_aliases_for_new_median_mode()
return true;
}
//------------------------------------------------------------------
bool blockchain_storage::print_tx_outputs_lookup(const crypto::hash& tx_id)const
{
CRITICAL_REGION_LOCAL(m_read_lock);
auto tx_ptr = m_db_transactions.find(tx_id);
if (!tx_ptr)
{
LOG_PRINT_RED_L0("Tx " << tx_id << " not found");
return true;
}
//amount -> index -> [{tx_id, rind_count}]
std::map<uint64_t, std::map<uint64_t, std::list<std::pair<crypto::hash,uint64_t > > > > usage_stat;
std::stringstream strm_tx;
CHECK_AND_ASSERT_MES(tx_ptr->tx.vout.size() == tx_ptr->m_global_output_indexes.size(), false, "Internal error: output size missmatch");
for (uint64_t i = 0; i!= tx_ptr->tx.vout.size();i++)
{
strm_tx << "[" << i << "]: " << print_money(tx_ptr->tx.vout[i].amount) << ENDL;
if (tx_ptr->tx.vout[i].target.type() != typeid(currency::txout_to_key))
continue;
usage_stat[tx_ptr->tx.vout[i].amount][tx_ptr->m_global_output_indexes[i]];
}
LOG_PRINT_L0("Lookup in all transactions....");
for (uint64_t i = 0; i != m_db_blocks.size(); i++)
{
auto block_ptr = m_db_blocks[i];
for (auto block_tx_id : block_ptr->bl.tx_hashes)
{
auto block_tx_ptr = m_db_transactions.find(block_tx_id);
for (auto txi_in : block_tx_ptr->tx.vin)
{
if(txi_in.type() != typeid(currency::txin_to_key))
continue;
currency::txin_to_key& txi_in_tokey = boost::get<currency::txin_to_key>(txi_in);
uint64_t amount = txi_in_tokey.amount;
auto amount_it = usage_stat.find(amount);
if(amount_it == usage_stat.end())
continue;
for (txout_v& off : txi_in_tokey.key_offsets)
{
if(off.type() != typeid(uint64_t))
continue;
uint64_t index = boost::get<uint64_t>(off);
auto index_it = amount_it->second.find(index);
if(index_it == amount_it->second.end())
continue;
index_it->second.push_back(std::pair<crypto::hash, uint64_t>(block_tx_id, txi_in_tokey.key_offsets.size()));
}
}
}
}
std::stringstream ss;
for (auto& amount : usage_stat)
{
for (auto& index : amount.second)
{
ss << "[" << print_money(amount.first) << ":" << index.first << "]" << ENDL ;
for (auto& list_entry : index.second)
{
ss << " " << list_entry.first << ": " << list_entry.second << ENDL;
}
}
}
LOG_PRINT_L0("Results: " << ENDL << strm_tx.str() << ENDL << ss.str());
return true;
}
//------------------------------------------------------------------
bool blockchain_storage::have_tx_keyimges_as_spent(const transaction &tx) const
{
// check all tx's inputs for being already spent
@ -4547,6 +4675,10 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
powpos_str_entry << "PoW:\t" << proof_hash;
timestamp_str_entry << ", block ts: " << bei.bl.timestamp << " (diff: " << std::showpos << ts_diff << "s)";
}
//explanation of this code will be provided later with public announce
set_lost_tx_unmixable_for_height(bei.height);
LOG_PRINT_L1("+++++ BLOCK SUCCESSFULLY ADDED " << (is_pos_bl ? "[PoS]" : "[PoW]") << " Sq: " << sequence_factor
<< ENDL << "id:\t" << id << timestamp_str_entry.str()
<< ENDL << powpos_str_entry.str()

View file

@ -429,6 +429,7 @@ namespace currency
void inspect_blocks_index() const;
bool rebuild_tx_fee_medians();
bool validate_all_aliases_for_new_median_mode();
bool print_tx_outputs_lookup(const crypto::hash& tx_id) const;
private:
//-------------- DB containers --------------
@ -524,6 +525,9 @@ namespace currency
bool init_tx_fee_median();
bool update_tx_fee_median();
void initialize_db_solo_options_values();
bool set_lost_tx_unmixable();
bool set_lost_tx_unmixable_for_height(uint64_t height);
void patch_out_if_needed(txout_to_key& out, const crypto::hash& tx_id, uint64_t n)const ;
bool switch_to_alternative_blockchain(alt_chain_type& alt_chain);
void purge_alt_block_txs_hashs(const block& b);
void add_alt_block_txs_hashs(const block& b);
@ -690,7 +694,11 @@ namespace currency
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_find_tx);
CHECKED_GET_SPECIFIC_VARIANT(tx_ptr->tx.vout[n].target, const txout_to_key, outtk, false);
//explanation of this code will be provided later with public announce
patch_out_if_needed(const_cast<txout_to_key&>(outtk), tx_id, n);
CHECK_AND_ASSERT_MES(tx_in_to_key.key_offsets.size() >= 1, false, "internal error: tx input has empty key_offsets"); // should never happen as input correctness must be handled by the caller
bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(outtk.mix_attr, tx_in_to_key.key_offsets.size() - 1);
CHECK_AND_ASSERT_MES(mixattr_ok, false, "tx output #" << output_index << " violates mixin restrictions: mix_attr = " << static_cast<uint32_t>(outtk.mix_attr) << ", key_offsets.size = " << tx_in_to_key.key_offsets.size());

View file

@ -1,4 +1,4 @@
// Copyright (c) 2014-2018 Zano Project
// Copyright (c) 2014-2019 Zano Project
// Copyright (c) 2014-2018 The Louisdor Project
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
@ -8,13 +8,12 @@
#define CURRENCY_FORMATION_VERSION 84
#define CURRENCY_GENESIS_NONCE (CURRENCY_FORMATION_VERSION + 101011010121)// <-- will be changed to another nightmare*/; //bender's nightmare
#define CURRENCY_GENESIS_NONCE (CURRENCY_FORMATION_VERSION + 101011010121) //bender's nightmare
#define CURRENCY_MAX_BLOCK_NUMBER 500000000
#define CURRENCY_MAX_BLOCK_SIZE 500000000 // block header blob limit, never used!
#define CURRENCY_TX_MAX_ALLOWED_OUTS 2000
#define CURRENCY_PUBLIC_ADDRESS_TEXTBLOB_VER 0
#define CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX 197 // addresses start with 'Z'
#define CURRENCY_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX 0x3678 // integrated addresses start with 'iZ'
#define CURRENCY_MINED_MONEY_UNLOCK_WINDOW 10
@ -30,9 +29,6 @@
// TOTAL_MONEY_SUPPLY - total number coins to be generated
#define TOTAL_MONEY_SUPPLY ((uint64_t)(-1))
#define EMISSION_POS_REWARD_DEVIDER 5425518 // originally based on formula "1/((sqrt(1.05, (740*366)) - 1))" which is avr 5% per year, and then adjusted
#define EMISSION_POW_REWARD_DEVIDER 27098500 // originally based on formula "1/((sqrt(1.01, (740*366)) - 1))" which is avr 1% per year, and then adjusted
#define POS_START_HEIGHT 0
#define CURRENCY_REWARD_BLOCKS_WINDOW 400
@ -45,23 +41,17 @@
// COIN - number of smallest units in one coin
#define COIN ((uint64_t)1000000000000) // pow(10, CURRENCY_DISPLAY_DECIMAL_POINT)
#define BASE_REWARD_DUST_THRESHOLD ((uint64_t)1000000) // pow(10, 6) - change this will cause hard-fork!
#define DEFAULT_DUST_THRESHOLD ((uint64_t)0)//((uint64_t)100000) // pow(10, 5)
#define DEFAULT_DUST_THRESHOLD ((uint64_t)0)
#define TX_DEFAULT_FEE ((uint64_t)10000000000) // .01
#define TX_MINIMUM_FEE ((uint64_t)10000000000) // .01
// #define CURRENCY_FIXED_REWARD_ZONE_HEIGHT 300 // blocks will have fixed reward up to this height (including)
// #define CURRENCY_FIXED_REWARD_ZONE_REWARD_AMOUNT ((uint64_t)100000000) // should be TX_MINIMUM_FEE * CURRENCY_FIXED_REWARD_ZONE_FEE_MULTIPLIER
// #define CURRENCY_FIXED_REWARD_ZONE_FEE_MULTIPLIER 1000 // reward in minimum fees for a block in the zone
#define CURRENCY_BLOCK_REWARD 1000000000000 // 1.0 coin
#define CURRENCY_BLOCK_REWARD 1000000000000 // 1.0 coin == pow(10, CURRENCY_DISPLAY_DECIMAL_POINT)
#define WALLET_MAX_ALLOWED_OUTPUT_AMOUNT ((uint64_t)0xffffffffffffffffLL)
#define CURRENCY_MINER_TX_MAX_OUTS CURRENCY_TX_MAX_ALLOWED_OUTS
#define ORPHANED_BLOCKS_MAX_COUNT 100
#define DIFFICULTY_STARTER 1
#define DIFFICULTY_POS_TARGET 120 // seconds
#define DIFFICULTY_POW_TARGET 120 // seconds
@ -120,7 +110,7 @@
#define P2P_LOCAL_GRAY_PEERLIST_LIMIT 5000
#define P2P_DEFAULT_CONNECTIONS_COUNT 8
#define P2P_DEFAULT_HANDSHAKE_INTERVAL 60 //secondes
#define P2P_DEFAULT_HANDSHAKE_INTERVAL 60 //seconds
#define P2P_DEFAULT_PACKET_MAX_SIZE 50000000 //50000000 bytes maximum packet size
#define P2P_DEFAULT_PEERS_IN_HANDSHAKE 250
#define P2P_DEFAULT_CONNECTION_TIMEOUT 5000 //5 seconds

View file

@ -33,7 +33,7 @@ namespace currency
m_miner(this, m_blockchain_storage),
m_miner_address(boost::value_initialized<account_public_address>()),
m_starter_message_showed(false),
m_stop_handler(nullptr)
m_critical_error_handler(nullptr)
{
set_currency_protocol(pprotocol);
}
@ -48,9 +48,9 @@ namespace currency
m_mempool.set_protocol(m_pprotocol);
}
//-----------------------------------------------------------------------------------
void core::set_stop_handler(i_stop_handler *handler)
void core::set_critical_error_handler(i_critical_error_handler* handler)
{
m_stop_handler = handler;
m_critical_error_handler = handler;
}
//-----------------------------------------------------------------------------------
bool core::set_checkpoints(checkpoints&& chk_pts)
@ -685,6 +685,7 @@ namespace currency
}
m_prune_alt_blocks_interval.do_call([this](){return m_blockchain_storage.prune_aged_alt_blocks();});
m_check_free_space_interval.do_call([this](){ check_free_space(); return true; });
m_miner.on_idle();
m_mempool.on_idle();
return true;
@ -709,6 +710,17 @@ namespace currency
l->on_blockchain_update();
}
//-----------------------------------------------------------------------------------------------
#define MINIMUM_REQUIRED_FREE_SPACE_BYTES (1024 * 1024 * 100)
void core::check_free_space()
{
boost::filesystem::space_info si = boost::filesystem::space(m_config_folder);
if (si.available < MINIMUM_REQUIRED_FREE_SPACE_BYTES)
{
m_critical_error_handler->on_critical_low_free_space(si.available, MINIMUM_REQUIRED_FREE_SPACE_BYTES);
}
}
//-----------------------------------------------------------------------------------------------
}
#undef LOG_DEFAULT_CHANNEL

View file

@ -81,8 +81,8 @@ namespace currency
size_t get_alternative_blocks_count();
void set_currency_protocol(i_currency_protocol* pprotocol);
void set_stop_handler(i_stop_handler *handler);
i_stop_handler* get_stop_handler() const { return m_stop_handler; }
void set_critical_error_handler(i_critical_error_handler *handler);
i_critical_error_handler* get_critical_error_handler() const { return m_critical_error_handler; }
bool set_checkpoints(checkpoints&& chk_pts);
bool get_pool_transactions(std::list<transaction>& txs);
@ -136,17 +136,20 @@ namespace currency
void notify_blockchain_update_listeners();
void check_free_space();
blockchain_storage m_blockchain_storage;
tx_memory_pool m_mempool;
i_currency_protocol* m_pprotocol;
i_stop_handler* m_stop_handler;
i_critical_error_handler* m_critical_error_handler;
critical_section m_incoming_tx_lock;
miner m_miner;
account_public_address m_miner_address;
std::string m_config_folder;
currency_protocol_stub m_protocol_stub;
math_helper::once_a_time_seconds<60*60*12, false> m_prune_alt_blocks_interval;
math_helper::once_a_time_seconds<60, true> m_check_free_space_interval;
friend class tx_validate_inputs;
std::atomic<bool> m_starter_message_showed;

View file

@ -1396,9 +1396,9 @@ namespace currency
//-----------------------------------------------------------------------------------------------
bool check_outs_valid(const transaction& tx)
{
BOOST_FOREACH(const tx_out& out, tx.vout)
for(const tx_out& out : tx.vout)
{
CHECK_AND_NO_ASSERT_MES(0 < out.amount, false, "zero amount ouput in transaction id=" << get_transaction_hash(tx));
CHECK_AND_NO_ASSERT_MES(0 < out.amount, false, "zero amount output in transaction id=" << get_transaction_hash(tx));
if (out.target.type() == typeid(txout_to_key))
{
if (!check_key(boost::get<txout_to_key>(out.target).key))

View file

@ -131,12 +131,10 @@ namespace currency
if (!add_time_delta_and_check_time_sync(context.m_time_delta))
{
// serious time sync problem detected
i_stop_handler* ish(m_core.get_stop_handler());
if (ish != nullptr)
i_critical_error_handler* ceh(m_core.get_critical_error_handler());
if (ceh != nullptr && ceh->on_critical_time_sync_error())
{
// this is daemon -- stop immediately
ish->stop_handling();
LOG_ERROR(ENDL << ENDL << "Serious time sync problem detected, daemon will stop immediately" << ENDL << ENDL);
// error is handled by a callee, should not be ignored here, stop processing immideately
return true;
}
}

View file

@ -40,9 +40,13 @@ namespace currency
/************************************************************************/
/* */
/************************************************************************/
struct i_stop_handler
struct i_critical_error_handler
{
virtual void stop_handling() = 0;
// called by currency protocol when the time is critically out of sync
// return true if the error is not ignored and the called should not proceed
virtual bool on_critical_time_sync_error() = 0;
virtual bool on_critical_low_free_space(uint64_t available, uint64_t required) = 0;
};

View file

@ -43,6 +43,49 @@ namespace po = boost::program_options;
bool command_line_preprocessor(const boost::program_options::variables_map& vm);
template<typename p2psrv_t>
struct core_critical_error_handler_t : public currency::i_critical_error_handler
{
core_critical_error_handler_t(daemon_commands_handler& dch, p2psrv_t& p2psrv, bool dont_stop_on_time_error, bool dont_stop_on_low_space)
: dch(dch)
, p2psrv(p2psrv)
, dont_stop_on_time_error(dont_stop_on_time_error)
, dont_stop_on_low_space(dont_stop_on_low_space)
{}
// interface currency::i_critical_error_handler
virtual bool on_critical_time_sync_error() override
{
if (dont_stop_on_time_error)
return false; // ignore such errors
LOG_ERROR(ENDL << ENDL << "Serious time sync problem detected, daemon will stop immediately" << ENDL << ENDL);
// stop handling
dch.stop_handling();
return true; // the caller must stop processing
}
// interface currency::i_critical_error_handler
virtual bool on_critical_low_free_space(uint64_t available, uint64_t required) override
{
if (dont_stop_on_low_space)
return false; // ignore such errors
LOG_ERROR(ENDL << ENDL << "Free space at data directory is critically low (" << available / (1024 * 1024) << " MB, while " << required / (1024 * 1024) << " MB is required), daemon will stop immediately" << ENDL << ENDL);
// stop handling
dch.stop_handling();
p2psrv.send_stop_signal();
return true; // the caller must stop processing
}
daemon_commands_handler& dch;
p2psrv_t& p2psrv;
bool dont_stop_on_time_error;
bool dont_stop_on_low_space;
};
int main(int argc, char* argv[])
{
try
@ -82,6 +125,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_cmd_sett, command_line::arg_show_details);
command_line::add_arg(desc_cmd_sett, command_line::arg_show_rpc_autodoc);
command_line::add_arg(desc_cmd_sett, command_line::arg_disable_stop_if_time_out_of_sync);
command_line::add_arg(desc_cmd_sett, command_line::arg_disable_stop_on_low_free_space);
arg_market_disable.default_value = true;
@ -89,7 +133,8 @@ int main(int argc, char* argv[])
currency::core::init_options(desc_cmd_sett);
currency::core_rpc_server::init_options(desc_cmd_sett);
nodetool::node_server<currency::t_currency_protocol_handler<currency::core> >::init_options(desc_cmd_sett);
typedef nodetool::node_server<currency::t_currency_protocol_handler<currency::core> > p2psrv_t;
p2psrv_t::init_options(desc_cmd_sett);
currency::miner::init_options(desc_cmd_sett);
bc_services::bc_offers_service::init_options(desc_cmd_sett);
currency::stratum_server::init_options(desc_cmd_sett);
@ -163,14 +208,16 @@ int main(int argc, char* argv[])
offers_service.set_disabled(true);
currency::core ccore(NULL);
currency::t_currency_protocol_handler<currency::core> cprotocol(ccore, NULL );
nodetool::node_server<currency::t_currency_protocol_handler<currency::core> > p2psrv(cprotocol);
p2psrv_t p2psrv(cprotocol);
currency::core_rpc_server rpc_server(ccore, p2psrv, offers_service);
cprotocol.set_p2p_endpoint(&p2psrv);
ccore.set_currency_protocol(&cprotocol);
daemon_cmmands_handler dch(p2psrv, rpc_server);
if (!command_line::get_arg(vm, command_line::arg_disable_stop_if_time_out_of_sync))
ccore.set_stop_handler(&dch);
daemon_commands_handler dch(p2psrv, rpc_server);
core_critical_error_handler_t<p2psrv_t> cceh(dch, p2psrv,
command_line::get_arg(vm, command_line::arg_disable_stop_if_time_out_of_sync),
command_line::get_arg(vm, command_line::arg_disable_stop_on_low_free_space));
ccore.set_critical_error_handler(&cceh);
//ccore.get_blockchain_storage().get_attachment_services_manager().add_service(&offers_service);
std::shared_ptr<currency::stratum_server> stratum_server_ptr;
@ -309,7 +356,7 @@ int main(int argc, char* argv[])
LOG_PRINT_L0("Deinitializing p2p...");
p2psrv.deinit();
ccore.set_stop_handler(nullptr);
ccore.set_critical_error_handler(nullptr);
ccore.set_currency_protocol(NULL);
cprotocol.set_p2p_endpoint(NULL);

View file

@ -20,7 +20,7 @@
PUSH_WARNINGS
DISABLE_VS_WARNINGS(4100)
class daemon_cmmands_handler : public currency::i_stop_handler
class daemon_commands_handler
{
typedef nodetool::node_server<currency::t_currency_protocol_handler<currency::core> > srv_type;
srv_type& m_srv;
@ -28,45 +28,47 @@ class daemon_cmmands_handler : public currency::i_stop_handler
typedef epee::srv_console_handlers_binder<nodetool::node_server<currency::t_currency_protocol_handler<currency::core> > > cmd_binder_type;
cmd_binder_type m_cmd_binder;
public:
daemon_cmmands_handler(nodetool::node_server<currency::t_currency_protocol_handler<currency::core> >& srv, currency::core_rpc_server& rpc) :m_srv(srv), m_rpc(rpc)
daemon_commands_handler(nodetool::node_server<currency::t_currency_protocol_handler<currency::core> >& srv, currency::core_rpc_server& rpc) :m_srv(srv), m_rpc(rpc)
{
m_cmd_binder.set_handler("help", boost::bind(&console_handlers_binder::help, &m_cmd_binder, _1), "Show this help");
m_cmd_binder.set_handler("print_pl", boost::bind(&daemon_cmmands_handler::print_pl, this, _1), "Print peer list");
m_cmd_binder.set_handler("print_cn", boost::bind(&daemon_cmmands_handler::print_cn, this, _1), "Print connections");
m_cmd_binder.set_handler("print_bc", boost::bind(&daemon_cmmands_handler::print_bc, this, _1), "Print blockchain info in a given blocks range, print_bc <begin_height> [<end_height>]");
m_cmd_binder.set_handler("print_bc_tx", boost::bind(&daemon_cmmands_handler::print_bc_tx, this, _1), "Print blockchain info with trnsactions in a given blocks range, print_bc <begin_height> [<end_height>]");
//m_cmd_binder.set_handler("print_bci", boost::bind(&daemon_cmmands_handler::print_bci, this, _1));
m_cmd_binder.set_handler("print_bc_outs", boost::bind(&daemon_cmmands_handler::print_bc_outs, this, _1));
m_cmd_binder.set_handler("print_market", boost::bind(&daemon_cmmands_handler::print_market, this, _1));
m_cmd_binder.set_handler("print_bc_outs_stat", boost::bind(&daemon_cmmands_handler::print_bc_outs_stat, this, _1));
m_cmd_binder.set_handler("print_block", boost::bind(&daemon_cmmands_handler::print_block, this, _1), "Print block, print_block <block_hash> | <block_height>");
m_cmd_binder.set_handler("print_block_info", boost::bind(&daemon_cmmands_handler::print_block_info, this, _1), "Print block info, print_block <block_hash> | <block_height>");
m_cmd_binder.set_handler("print_tx", boost::bind(&daemon_cmmands_handler::print_tx, this, _1), "Print transaction, print_tx <transaction_hash>");
m_cmd_binder.set_handler("start_mining", boost::bind(&daemon_cmmands_handler::start_mining, this, _1), "Start mining for specified address, start_mining <addr> [threads=1]");
m_cmd_binder.set_handler("stop_mining", boost::bind(&daemon_cmmands_handler::stop_mining, this, _1), "Stop mining");
m_cmd_binder.set_handler("print_pool", boost::bind(&daemon_cmmands_handler::print_pool, this, _1), "Print transaction pool (long format)");
m_cmd_binder.set_handler("print_pool_sh", boost::bind(&daemon_cmmands_handler::print_pool_sh, this, _1), "Print transaction pool (short format)");
m_cmd_binder.set_handler("show_hr", boost::bind(&daemon_cmmands_handler::show_hr, this, _1), "Start showing hash rate");
m_cmd_binder.set_handler("hide_hr", boost::bind(&daemon_cmmands_handler::hide_hr, this, _1), "Stop showing hash rate");
m_cmd_binder.set_handler("save", boost::bind(&daemon_cmmands_handler::save, this, _1), "Save blockchain");
m_cmd_binder.set_handler("print_daemon_stat", boost::bind(&daemon_cmmands_handler::print_daemon_stat, this, _1), "Print daemon stat");
m_cmd_binder.set_handler("print_debug_stat", boost::bind(&daemon_cmmands_handler::print_debug_stat, this, _1), "Print debug stat info");
m_cmd_binder.set_handler("get_transactions_statics", boost::bind(&daemon_cmmands_handler::get_transactions_statistics, this, _1), "Calculates transactions statistics");
m_cmd_binder.set_handler("force_relay_tx_pool", boost::bind(&daemon_cmmands_handler::force_relay_tx_pool, this, _1), "re-relay all transactions from pool");
m_cmd_binder.set_handler("enable_channel", boost::bind(&daemon_cmmands_handler::enable_channel, this, _1), "Enable specified log channel");
m_cmd_binder.set_handler("disable_channel", boost::bind(&daemon_cmmands_handler::disable_channel, this, _1), "Enable specified log channel");
m_cmd_binder.set_handler("clear_cache", boost::bind(&daemon_cmmands_handler::clear_cache, this, _1), "Clear blockchain storage cache");
m_cmd_binder.set_handler("clear_altblocks", boost::bind(&daemon_cmmands_handler::clear_altblocks, this, _1), "Clear blockchain storage cache");
m_cmd_binder.set_handler("truncate_bc", boost::bind(&daemon_cmmands_handler::truncate_bc, this, _1), "Truncate blockchain to specified height");
m_cmd_binder.set_handler("inspect_block_index", boost::bind(&daemon_cmmands_handler::inspect_block_index, this, _1), "Inspects block index for internal errors");
m_cmd_binder.set_handler("print_db_performance_data", boost::bind(&daemon_cmmands_handler::print_db_performance_data, this, _1), "Dumps all db containers performance counters");
m_cmd_binder.set_handler("search_by_id", boost::bind(&daemon_cmmands_handler::search_by_id, this, _1), "Search all possible elemets by given id");
m_cmd_binder.set_handler("find_key_image", boost::bind(&daemon_cmmands_handler::find_key_image, this, _1), "Try to find tx related to key_image");
m_cmd_binder.set_handler("rescan_aliases", boost::bind(&daemon_cmmands_handler::rescan_aliases, this, _1), "Debug function");
m_cmd_binder.set_handler("forecast_difficulty", boost::bind(&daemon_cmmands_handler::forecast_difficulty, this, _1), "Prints PoW and PoS difficulties for as many future blocks as possible based on current conditions");
m_cmd_binder.set_handler("print_deadlock_guard", boost::bind(&daemon_cmmands_handler::print_deadlock_guard, this, _1), "Print all threads which is blocked or involved in mutex ownership");
m_cmd_binder.set_handler("print_block_from_hex_blob", boost::bind(&daemon_cmmands_handler::print_block_from_hex_blob, this, _1), "Unserialize block from hex binary data to json-like representation");
m_cmd_binder.set_handler("print_tx_from_hex_blob", boost::bind(&daemon_cmmands_handler::print_tx_from_hex_blob, this, _1), "Unserialize transaction from hex binary data to json-like representation");
m_cmd_binder.set_handler("print_pl", boost::bind(&daemon_commands_handler::print_pl, this, _1), "Print peer list");
m_cmd_binder.set_handler("print_cn", boost::bind(&daemon_commands_handler::print_cn, this, _1), "Print connections");
m_cmd_binder.set_handler("print_bc", boost::bind(&daemon_commands_handler::print_bc, this, _1), "Print blockchain info in a given blocks range, print_bc <begin_height> [<end_height>]");
m_cmd_binder.set_handler("print_bc_tx", boost::bind(&daemon_commands_handler::print_bc_tx, this, _1), "Print blockchain info with trnsactions in a given blocks range, print_bc <begin_height> [<end_height>]");
//m_cmd_binder.set_handler("print_bci", boost::bind(&daemon_commands_handler::print_bci, this, _1));
m_cmd_binder.set_handler("print_bc_outs", boost::bind(&daemon_commands_handler::print_bc_outs, this, _1));
m_cmd_binder.set_handler("print_market", boost::bind(&daemon_commands_handler::print_market, this, _1));
m_cmd_binder.set_handler("print_bc_outs_stat", boost::bind(&daemon_commands_handler::print_bc_outs_stat, this, _1));
m_cmd_binder.set_handler("print_block", boost::bind(&daemon_commands_handler::print_block, this, _1), "Print block, print_block <block_hash> | <block_height>");
m_cmd_binder.set_handler("print_block_info", boost::bind(&daemon_commands_handler::print_block_info, this, _1), "Print block info, print_block <block_hash> | <block_height>");
m_cmd_binder.set_handler("print_tx", boost::bind(&daemon_commands_handler::print_tx, this, _1), "Print transaction, print_tx <transaction_hash>");
m_cmd_binder.set_handler("start_mining", boost::bind(&daemon_commands_handler::start_mining, this, _1), "Start mining for specified address, start_mining <addr> [threads=1]");
m_cmd_binder.set_handler("stop_mining", boost::bind(&daemon_commands_handler::stop_mining, this, _1), "Stop mining");
m_cmd_binder.set_handler("print_pool", boost::bind(&daemon_commands_handler::print_pool, this, _1), "Print transaction pool (long format)");
m_cmd_binder.set_handler("print_pool_sh", boost::bind(&daemon_commands_handler::print_pool_sh, this, _1), "Print transaction pool (short format)");
m_cmd_binder.set_handler("show_hr", boost::bind(&daemon_commands_handler::show_hr, this, _1), "Start showing hash rate");
m_cmd_binder.set_handler("hide_hr", boost::bind(&daemon_commands_handler::hide_hr, this, _1), "Stop showing hash rate");
m_cmd_binder.set_handler("save", boost::bind(&daemon_commands_handler::save, this, _1), "Save blockchain");
m_cmd_binder.set_handler("print_daemon_stat", boost::bind(&daemon_commands_handler::print_daemon_stat, this, _1), "Print daemon stat");
m_cmd_binder.set_handler("print_debug_stat", boost::bind(&daemon_commands_handler::print_debug_stat, this, _1), "Print debug stat info");
m_cmd_binder.set_handler("get_transactions_statics", boost::bind(&daemon_commands_handler::get_transactions_statistics, this, _1), "Calculates transactions statistics");
m_cmd_binder.set_handler("force_relay_tx_pool", boost::bind(&daemon_commands_handler::force_relay_tx_pool, this, _1), "re-relay all transactions from pool");
m_cmd_binder.set_handler("enable_channel", boost::bind(&daemon_commands_handler::enable_channel, this, _1), "Enable specified log channel");
m_cmd_binder.set_handler("disable_channel", boost::bind(&daemon_commands_handler::disable_channel, this, _1), "Enable specified log channel");
m_cmd_binder.set_handler("clear_cache", boost::bind(&daemon_commands_handler::clear_cache, this, _1), "Clear blockchain storage cache");
m_cmd_binder.set_handler("clear_altblocks", boost::bind(&daemon_commands_handler::clear_altblocks, this, _1), "Clear blockchain storage cache");
m_cmd_binder.set_handler("truncate_bc", boost::bind(&daemon_commands_handler::truncate_bc, this, _1), "Truncate blockchain to specified height");
m_cmd_binder.set_handler("inspect_block_index", boost::bind(&daemon_commands_handler::inspect_block_index, this, _1), "Inspects block index for internal errors");
m_cmd_binder.set_handler("print_db_performance_data", boost::bind(&daemon_commands_handler::print_db_performance_data, this, _1), "Dumps all db containers performance counters");
m_cmd_binder.set_handler("search_by_id", boost::bind(&daemon_commands_handler::search_by_id, this, _1), "Search all possible elemets by given id");
m_cmd_binder.set_handler("find_key_image", boost::bind(&daemon_commands_handler::find_key_image, this, _1), "Try to find tx related to key_image");
m_cmd_binder.set_handler("rescan_aliases", boost::bind(&daemon_commands_handler::rescan_aliases, this, _1), "Debug function");
m_cmd_binder.set_handler("forecast_difficulty", boost::bind(&daemon_commands_handler::forecast_difficulty, this, _1), "Prints PoW and PoS difficulties for as many future blocks as possible based on current conditions");
m_cmd_binder.set_handler("print_deadlock_guard", boost::bind(&daemon_commands_handler::print_deadlock_guard, this, _1), "Print all threads which is blocked or involved in mutex ownership");
m_cmd_binder.set_handler("print_block_from_hex_blob", boost::bind(&daemon_commands_handler::print_block_from_hex_blob, this, _1), "Unserialize block from hex binary data to json-like representation");
m_cmd_binder.set_handler("print_tx_from_hex_blob", boost::bind(&daemon_commands_handler::print_tx_from_hex_blob, this, _1), "Unserialize transaction from hex binary data to json-like representation");
m_cmd_binder.set_handler("print_tx_outputs_usage", boost::bind(&daemon_commands_handler::print_tx_outputs_usage, this, _1), "Analyse if tx outputs for involved in subsequent transactions");
}
bool start_handling()
@ -75,8 +77,7 @@ public:
return true;
}
// interface currency::i_stop_handler
virtual void stop_handling() override
void stop_handling()
{
m_cmd_binder.stop_handling();
}
@ -84,17 +85,17 @@ public:
private:
// //--------------------------------------------------------------------------------
// std::string get_commands_str()
// {
// return m_cmd_binder.get_usage();
// }
// //--------------------------------------------------------------------------------
// bool help(const std::vector<std::string>& /*args*/)
// {
// std::cout << get_commands_str() << ENDL;
// return true;
// }
// //--------------------------------------------------------------------------------
// std::string get_commands_str()
// {
// return m_cmd_binder.get_usage();
// }
// //--------------------------------------------------------------------------------
// bool help(const std::vector<std::string>& /*args*/)
// {
// std::cout << get_commands_str() << ENDL;
// return true;
// }
//--------------------------------------------------------------------------------
bool print_pl(const std::vector<std::string>& args)
{
@ -165,23 +166,24 @@ private:
{
m_srv.get_payload_object().get_core().get_blockchain_storage().reset_db_cache();
return true;
}
}
bool clear_altblocks(const std::vector<std::string>& args)
{
m_srv.get_payload_object().get_core().get_blockchain_storage().clear_altblocks();
return true;
}
//--------------------------------------------------------------------------------
bool show_hr(const std::vector<std::string>& args)
{
if(!m_srv.get_payload_object().get_core().get_miner().is_mining())
{
std::cout << "Mining is not started. You need start mining before you can see hash rate." << ENDL;
} else
{
m_srv.get_payload_object().get_core().get_miner().do_print_hashrate(true);
}
if (!m_srv.get_payload_object().get_core().get_miner().is_mining())
{
std::cout << "Mining is not started. You need start mining before you can see hash rate." << ENDL;
}
else
{
m_srv.get_payload_object().get_core().get_miner().do_print_hashrate(true);
}
return true;
}
//--------------------------------------------------------------------------------
@ -193,7 +195,7 @@ private:
//--------------------------------------------------------------------------------
bool print_bc_outs(const std::vector<std::string>& args)
{
if(args.size() != 1)
if (args.size() != 1)
{
std::cout << "need file path as parameter" << ENDL;
return true;
@ -219,25 +221,25 @@ private:
//--------------------------------------------------------------------------------
bool print_cn(const std::vector<std::string>& args)
{
m_srv.get_payload_object().log_connections();
return true;
m_srv.get_payload_object().log_connections();
return true;
}
//--------------------------------------------------------------------------------
bool print_bc(const std::vector<std::string>& args)
{
if(!args.size())
if (!args.size())
{
std::cout << "need block index parameter" << ENDL;
return false;
}
uint64_t start_index = 0;
uint64_t end_block_parametr = m_srv.get_payload_object().get_core().get_current_blockchain_size();
if(!string_tools::get_xtype_from_string(start_index, args[0]))
if (!string_tools::get_xtype_from_string(start_index, args[0]))
{
std::cout << "wrong starter block index parameter" << ENDL;
return false;
}
if(args.size() >1 && !string_tools::get_xtype_from_string(end_block_parametr, args[1]))
if (args.size() > 1 && !string_tools::get_xtype_from_string(end_block_parametr, args[1]))
{
std::cout << "wrong end block index parameter" << ENDL;
return false;
@ -273,7 +275,7 @@ private:
{
m_srv.get_payload_object().get_core().get_blockchain_storage().print_db_cache_perfeormance_data();
return true;
}
}
//--------------------------------------------------------------------------------
bool search_by_id(const std::vector<std::string>& args)
{
@ -286,7 +288,7 @@ private:
crypto::hash id = currency::null_hash;
if (!parse_hash256(args[0], id))
{
std::cout << "specified ID parameter '"<< args[0] << "' is wrong" << ENDL;
std::cout << "specified ID parameter '" << args[0] << "' is wrong" << ENDL;
return false;
}
std::list<std::string> res_list;
@ -372,7 +374,7 @@ private:
res = ::serialization::parse_binary(bin_buff, item);
CHECK_AND_ASSERT_MES(res, false, "failed to parse binary");
LOG_PRINT_L0("OBJECT " << typeid(item).name() << ": " << ENDL << obj_to_json_str(item));
return true;
}
@ -415,43 +417,43 @@ private:
//--------------------------------------------------------------------------------
bool export_tx_pool_to_json(const std::vector<std::string>& args)
{
// if (!args.size())
// {
// std::cout << "need block blob parameter" << ENDL;
// return false;
// }
// tx_pool_exported_blobs tx_pool_json;
// m_srv.get_payload_object().get_core().get_tx_pool().get_all_transactions_details(tx_pool_json.all_txs_details);
// std::string pool_state = epee::serialization::store_t_to_json(tx_pool_json);
// CHECK_AND_ASSERT_THROW(pool_state.size(), false, "Unable to export pool");
//
// bool r = file_io_utils::save_string_to_file(args[0], pool_state);
// CHECK_AND_ASSERT_THROW(r, false, "Unable to export pool");
// LOG_PRINT_GREEN("Exported OK(" << tx_pool_json.all_txs_details.size() <<" transactions)");
// if (!args.size())
// {
// std::cout << "need block blob parameter" << ENDL;
// return false;
// }
// tx_pool_exported_blobs tx_pool_json;
// m_srv.get_payload_object().get_core().get_tx_pool().get_all_transactions_details(tx_pool_json.all_txs_details);
// std::string pool_state = epee::serialization::store_t_to_json(tx_pool_json);
// CHECK_AND_ASSERT_THROW(pool_state.size(), false, "Unable to export pool");
//
// bool r = file_io_utils::save_string_to_file(args[0], pool_state);
// CHECK_AND_ASSERT_THROW(r, false, "Unable to export pool");
// LOG_PRINT_GREEN("Exported OK(" << tx_pool_json.all_txs_details.size() <<" transactions)");
return true;
}
//--------------------------------------------------------------------------------
bool import_tx_pool_to_json(const std::vector<std::string>& args)
{
// if (!args.size())
// {
// std::cout << "need block blob parameter" << ENDL;
// return false;
// }
//
// std::string buff;
// bool r = file_io_utils::load_file_to_string(args[0], buff);
//
// tx_pool_exported_blobs tx_pool_json;
//
//
// m_srv.get_payload_object().get_core().get_tx_pool().get_all_transactions_details(tx_pool_json.all_txs_details);
// std::string pool_state = epee::serialization::store_t_to_json(tx_pool_json);
// CHECK_AND_ASSERT_THROW(pool_state.size(), false, "Unable to export pool");
//
//
// CHECK_AND_ASSERT_THROW(r, false, "Unable to export pool");
// LOG_PRINT_GREEN("Exported OK(" << tx_pool_json.all_txs_details.size() << " transactions)");
// if (!args.size())
// {
// std::cout << "need block blob parameter" << ENDL;
// return false;
// }
//
// std::string buff;
// bool r = file_io_utils::load_file_to_string(args[0], buff);
//
// tx_pool_exported_blobs tx_pool_json;
//
//
// m_srv.get_payload_object().get_core().get_tx_pool().get_all_transactions_details(tx_pool_json.all_txs_details);
// std::string pool_state = epee::serialization::store_t_to_json(tx_pool_json);
// CHECK_AND_ASSERT_THROW(pool_state.size(), false, "Unable to export pool");
//
//
// CHECK_AND_ASSERT_THROW(r, false, "Unable to export pool");
// LOG_PRINT_GREEN("Exported OK(" << tx_pool_json.all_txs_details.size() << " transactions)");
return true;
}
//--------------------------------------------------------------------------------
@ -521,7 +523,7 @@ private:
if (r)
{
// currency::block& block = bei.bl;
LOG_PRINT_GREEN("------------------ block_id: " << bei.id << " ------------------" << ENDL << epee::serialization::store_t_to_json(bei) , LOG_LEVEL_0);
LOG_PRINT_GREEN("------------------ block_id: " << bei.id << " ------------------" << ENDL << epee::serialization::store_t_to_json(bei), LOG_LEVEL_0);
}
else
{
@ -550,7 +552,7 @@ private:
if (r)
{
// currency::block& block = bei.bl;
// currency::block& block = bei.bl;
LOG_PRINT_GREEN("------------------ block_id: " << get_block_hash(bei.bl) << " ------------------" << ENDL << currency::obj_to_json_str(bei), LOG_LEVEL_0);
m_srv.get_payload_object().get_core().get_blockchain_storage().calc_tx_cummulative_blob(bei.bl);
}
@ -622,11 +624,11 @@ private:
return true;
}
// std::vector<crypto::hash> tx_ids;
// tx_ids.push_back(tx_hash);
// std::list<currency::transaction> txs;
// std::list<crypto::hash> missed_ids;
// m_srv.get_payload_object().get_core().get_transactions(tx_ids, txs, missed_ids);
// std::vector<crypto::hash> tx_ids;
// tx_ids.push_back(tx_hash);
// std::list<currency::transaction> txs;
// std::list<crypto::hash> missed_ids;
// m_srv.get_payload_object().get_core().get_transactions(tx_ids, txs, missed_ids);
currency::transaction_chain_entry tx_entry = AUTO_VAL_INIT(tx_entry);
@ -654,10 +656,10 @@ private:
for (auto at : tx.attachment)
{
if (at.type() == typeid(currency::tx_service_attachment))
{
{
const currency::tx_service_attachment& sa = boost::get<currency::tx_service_attachment>(at);
ss << "++++++++++++++++++++++++++++++++ " << ENDL;
ss << "[SERVICE_ATTACHMENT]: ID = \'" << sa.service_id << "\', INSTRUCTION: \'" << sa.instruction << "\'" << ENDL;
ss << "[SERVICE_ATTACHMENT]: ID = \'" << sa.service_id << "\', INSTRUCTION: \'" << sa.instruction << "\'" << ENDL;
if (!(sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY))
{
@ -675,6 +677,27 @@ private:
LOG_PRINT_GREEN(ss.str(), LOG_LEVEL_0);
return true;
}
//--------------------------------------------------------------------------------
bool print_tx_outputs_usage(const std::vector<std::string>& args)
{
if (args.empty())
{
std::cout << "expected: print_tx <transaction hash>" << std::endl;
return true;
}
const std::string& str_hash = args.front();
crypto::hash tx_hash;
if (!parse_hash256(str_hash, tx_hash))
{
return true;
}
m_srv.get_payload_object().get_core().get_blockchain_storage().print_tx_outputs_lookup(tx_hash);
return true;
}
//--------------------------------------------------------------------------------
bool print_pool(const std::vector<std::string>& args)
{
@ -689,20 +712,20 @@ private:
} //--------------------------------------------------------------------------------
bool start_mining(const std::vector<std::string>& args)
{
if(!args.size())
if (!args.size())
{
std::cout << "Please, specify wallet address to mine for: start_mining <addr> [threads=1]" << std::endl;
return true;
}
currency::account_public_address adr;
if(!currency::get_account_address_from_str(adr, args.front()))
if (!currency::get_account_address_from_str(adr, args.front()))
{
std::cout << "target account address has wrong format" << std::endl;
return true;
}
size_t threads_count = 1;
if(args.size() > 1)
if (args.size() > 1)
{
bool ok = string_tools::get_xtype_from_string(threads_count, args[1]);
threads_count = (ok && 0 < threads_count) ? threads_count : 1;
@ -749,7 +772,7 @@ private:
else
ss << " ";
ss << std::setw(10) << std::left << pow_diffs[i].second;
ss << " ";
ss << std::setw(6) << std::left << pos_diffs[i].first;
if (i == 0)
@ -769,9 +792,9 @@ private:
LOG_PRINT_L0(ENDL << epee::deadlock_guard_singleton::get_dlg_state());
return true;
}
};
POP_WARNINGS
POP_WARNINGS

View file

@ -1534,10 +1534,17 @@ void daemon_backend::wallet_vs_options::worker_func()
{
pos_minin_interval.do_call([this](){
tools::wallet2::mining_context ctx = AUTO_VAL_INIT(ctx);
LOG_PRINT_L1(w->get()->get_log_prefix() + " Starting PoS mint iteration");
LOG_PRINT_L1(get_log_prefix() + " Starting PoS mint iteration");
if (!w->get()->fill_mining_context(ctx) || ctx.rsp.status != CORE_RPC_STATUS_OK)
{
LOG_PRINT_L1(get_log_prefix() + " cannot obtain PoS mining context, skip iteration");
return true;
LOG_PRINT_L1(w->get()->get_log_prefix() + " POS_ENTRIES: " << ctx.sp.pos_entries.size());
}
uint64_t pos_entries_amount = 0;
for (auto& ent : ctx.sp.pos_entries)
pos_entries_amount += ent.amount;
tools::wallet2::scan_pos(ctx, break_mining_loop, [this](){
return *plast_daemon_network_state == currency::COMMAND_RPC_GET_INFO::daemon_network_state_online && *plast_daemon_height == last_wallet_synch_height;
}, core_conf);
@ -1546,7 +1553,7 @@ void daemon_backend::wallet_vs_options::worker_func()
{
w->get()->build_minted_block(ctx.sp, ctx.rsp);
}
LOG_PRINT_L1(w->get()->get_log_prefix() + " PoS mint iteration finished(iterations: " << ctx.rsp.iterations_processed << "," << ctx.rsp.status << ")");
LOG_PRINT_L1(get_log_prefix() << " PoS mining iteration finished, status: " << ctx.rsp.status << ", used " << ctx.sp.pos_entries.size() << " entries with total amount: " << currency::print_money_brief(pos_entries_amount) << ", processed: " << ctx.rsp.iterations_processed << " iter.");
return true;
});
}

View file

@ -71,6 +71,7 @@ public:
std::thread miner_thread;
void worker_func();
std::string get_log_prefix() const { return std::string("[") + epee::string_tools::num_to_string_fast(wallet_id) + ":" + w->get()->get_log_prefix() + "]"; }
~wallet_vs_options();
};

View file

@ -286,6 +286,7 @@
"FEE": "Fee",
"ADDRESS": "Address",
"DETAILS": {
"PAYMENT_ID": "Payment ID",
"ID": "Transaction ID",
"SIZE": "Transaction size",
"SIZE_VALUE": "{{value}} bytes",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -26,10 +26,10 @@
"@ng-select/ng-select": "^2.16.2",
"@ngx-translate/core": "^11.0.0",
"@ngx-translate/http-loader": "^4.0.0",
"angular-highcharts": "^7.0.2",
"angular-highcharts": "^7.1.0",
"bignumber.js": "^8.0.2",
"core-js": "^2.5.4",
"highcharts": "^6.2.0",
"highcharts": "^7.0.3",
"idlejs": "^2.0.1",
"json-bignumber": "^1.0.1",
"ngx-contextmenu": "^5.1.1",
@ -42,7 +42,6 @@
"@angular/cli": "~7.0.2",
"@angular/compiler-cli": "^7.2.10",
"@angular/language-service": "~7.0.0",
"@types/highcharts": "^5.0.34",
"@types/jasmine": "~2.8.8",
"@types/jasminewd2": "~2.0.3",
"@types/node": "~8.9.4",

View file

@ -17,6 +17,13 @@
<span class="cell label" [style.flex-basis]="sizes[2] + 'px'">{{ 'HISTORY.DETAILS.OUTPUTS' | translate }}</span>
<span class="cell value" [style.flex-basis]="sizes[3] + 'px'" tooltip="{{outputs.join(', ')}}" placement="top" tooltipClass="table-tooltip table-tooltip-dimensions" [delay]="500" [showWhenNoOverflow]="false">{{outputs.join(', ')}}</span>
</div>
<div class="row">
<span class="cell label" [style.flex-basis]="sizes[0] + 'px'">{{ 'HISTORY.DETAILS.PAYMENT_ID' | translate }}</span>
<span class="cell value" [style.flex-basis]="sizes[1] + sizes[2] + sizes[3] + 'px'"
tooltip="{{transaction.payment_id}}" placement="top" tooltipClass="table-tooltip comment-tooltip" [delay]="500" [showWhenNoOverflow]="false">
{{transaction.payment_id}}
</span>
</div>
<div class="row">
<span class="cell label" [style.flex-basis]="sizes[0] + 'px'">{{ 'HISTORY.DETAILS.COMMENT' | translate }}</span>
<span class="cell value" [style.flex-basis]="sizes[1] + sizes[2] + sizes[3] + 'px'"

View file

@ -28,7 +28,7 @@ import { TypingMessageComponent } from './typing-message/typing-message.componen
import { StakingComponent } from './staking/staking.component';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
@ -46,24 +46,31 @@ import { StakingSwitchComponent } from './_helpers/directives/staking-switch/sta
import { ModalContainerComponent } from './_helpers/directives/modal-container/modal-container.component';
import { TransactionDetailsComponent } from './_helpers/directives/transaction-details/transaction-details.component';
import { ContextMenuModule } from 'ngx-contextmenu';
import { ChartModule, HIGHCHARTS_MODULES } from 'angular-highcharts';
import * as highcharts from 'highcharts';
import exporting from 'highcharts/modules/exporting.src';
import { ProgressContainerComponent } from './_helpers/directives/progress-container/progress-container.component';
import { InputDisableSelectionDirective } from './_helpers/directives/input-disable-selection/input-disable-selection.directive';
export function HttpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient, './assets/i18n/', '.json');
}
import { ChartModule, HIGHCHARTS_MODULES, Highcharts} from 'angular-highcharts';
import { ProgressContainerComponent } from './_helpers/directives/progress-container/progress-container.component';
import { InputDisableSelectionDirective } from './_helpers/directives/input-disable-selection/input-disable-selection.directive';
// import * as more from 'highcharts/highcharts-more.src';
// import * as exporting from 'highcharts/modules/exporting.src';
// import * as highstock from 'highcharts/modules/stock.src';
Highcharts.setOptions({
global: {
useUTC: false
}
});
export function highchartsFactory() {
// Default options.
highcharts.setOptions({
global: {
useUTC: false
}
});
return [exporting];
}
@NgModule({
declarations: [
@ -125,6 +132,7 @@ Highcharts.setOptions({
ModalService,
MoneyToIntPipe,
IntToMoneyPipe,
{ provide: HIGHCHARTS_MODULES, useFactory: highchartsFactory }
// {provide: HIGHCHARTS_MODULES, useFactory: () => [ highstock, more, exporting ] }
],
entryComponents: [

View file

@ -286,6 +286,7 @@
"FEE": "Fee",
"ADDRESS": "Address",
"DETAILS": {
"PAYMENT_ID": "Payment ID",
"ID": "Transaction ID",
"SIZE": "Transaction size",
"SIZE_VALUE": "{{value}} bytes",

View file

@ -58,13 +58,18 @@ namespace tools
}
bool password_container::read_password()
{
return read_password("password: ");
}
bool password_container::read_password(const std::string& prompt_text)
{
clear();
bool r;
if (is_cin_tty())
{
std::cout << "password: ";
std::cout << prompt_text;
r = read_from_tty();
}
else

View file

@ -26,6 +26,7 @@ namespace tools
const std::string& password() const { return m_password; }
void password(std::string&& val) { m_password = std::move(val); m_empty = false; }
bool read_password();
bool read_password(const std::string& prompt_text);
private:
bool read_from_file();

View file

@ -49,6 +49,7 @@ namespace
const command_line::arg_descriptor<int> arg_daemon_port = {"daemon-port", "Use daemon instance at port <arg> instead of default", 0};
const command_line::arg_descriptor<uint32_t> arg_log_level = {"set-log", "", 0, true};
const command_line::arg_descriptor<bool> arg_do_pos_mining = { "do-pos-mining", "Do PoS mining", false, false };
const command_line::arg_descriptor<std::string> arg_restore_wallet = { "restore-wallet", "Restore wallet from the seed phrase and save it to <arg>", "" };
const command_line::arg_descriptor<bool> arg_offline_mode = { "offline-mode", "Don't connect to daemon, work offline (for cold-signing process)", false, true };
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
@ -204,19 +205,25 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer, this, _1), "transfer <mixin_count> <addr_1> <amount_1> [<addr_2> <amount_2> ... <addr_N> <amount_N>] [payment_id] - Transfer <amount_1>,... <amount_N> to <address_1>,... <address_N>, respectively. <mixin_count> is the number of transactions yours is indistinguishable from (from 0 to maximum available)");
m_cmd_binder.set_handler("set_log", boost::bind(&simple_wallet::set_log, this, _1), "set_log <level> - Change current log detalisation level, <level> is a number 0-4");
m_cmd_binder.set_handler("enable_concole_logger", boost::bind(&simple_wallet::enable_concole_logger, this, _1), "Enables console logging");
m_cmd_binder.set_handler("address", boost::bind(&simple_wallet::print_address, this, _1), "Show current wallet public address");
m_cmd_binder.set_handler("resync", boost::bind(&simple_wallet::resync_wallet, this, _1), "Causes wallet to reset all transfers and re-synchronize wallet");
m_cmd_binder.set_handler("save", boost::bind(&simple_wallet::save, this, _1), "Save wallet synchronized data");
m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::help, this, _1), "Show this help");
m_cmd_binder.set_handler("get_transfer_info", boost::bind(&simple_wallet::get_transfer_info, this, _1), "displays transfer info by key_image or index");
m_cmd_binder.set_handler("scan_for_collision", boost::bind(&simple_wallet::scan_for_key_image_collisions, this, _1), "Rescan transfers for key image collisions");
m_cmd_binder.set_handler("fix_collisions", boost::bind(&simple_wallet::fix_collisions, this, _1), "Rescan transfers for key image collisions");
m_cmd_binder.set_handler("scan_transfers_for_id", boost::bind(&simple_wallet::scan_transfers_for_id, this, _1), "Rescan transfers for tx_id");
m_cmd_binder.set_handler("scan_transfers_for_ki", boost::bind(&simple_wallet::scan_transfers_for_ki, this, _1), "Rescan transfers for key image");
m_cmd_binder.set_handler("address", boost::bind(&simple_wallet::print_address, this, _1), "Show current wallet public address");
m_cmd_binder.set_handler("integrated_address", boost::bind(&simple_wallet::integrated_address, this, _1), "integrated_address [<payment_id>|<integrated_address] - encodes given payment_id along with wallet's address into an integrated address (random payment_id will be used if none is provided). Decodes given integrated_address into standard address");
m_cmd_binder.set_handler("show_seed", boost::bind(&simple_wallet::show_seed, this, _1), "Display secret 24 word phrase that could be used to recover this wallet");
m_cmd_binder.set_handler("spendkey", boost::bind(&simple_wallet::spendkey, this, _1), "Display secret spend key");
m_cmd_binder.set_handler("viewkey", boost::bind(&simple_wallet::viewkey, this, _1), "Display secret view key");
m_cmd_binder.set_handler("get_tx_key", boost::bind(&simple_wallet::get_tx_key, this, _1), "Get transaction one-time secret key (r) for a given <txid>");
m_cmd_binder.set_handler("save", boost::bind(&simple_wallet::save, this, _1), "Save wallet synchronized data");
m_cmd_binder.set_handler("save_watch_only", boost::bind(&simple_wallet::save_watch_only, this, _1), "save_watch_only <filename> <password> - save as watch-only wallet file.");
m_cmd_binder.set_handler("sign_transfer", boost::bind(&simple_wallet::sign_transfer, this, _1), "sign_transfer <unsgined_tx_file> <signed_tx_file> - sign unsigned tx from a watch-only wallet");
m_cmd_binder.set_handler("submit_transfer", boost::bind(&simple_wallet::submit_transfer, this, _1), "submit_transfer <signed_tx_file> - broadcast signed tx");
}
@ -262,12 +269,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
return false;
}
size_t c = 0;
if(!m_generate_new.empty()) ++c;
if(!m_wallet_file.empty()) ++c;
if (1 != c)
if (m_wallet_file.empty() && m_generate_new.empty() && m_restore_wallet.empty())
{
fail_msg_writer() << "you must specify --wallet-file or --generate-new-wallet params";
fail_msg_writer() << "you must specify --wallet-file, --generate-new-wallet or --restore-wallet";
return false;
}
@ -310,6 +314,24 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
CHECK_AND_ASSERT_MES(r, false, "account creation failed");
}
else if (!m_restore_wallet.empty())
{
if (boost::filesystem::exists(m_restore_wallet))
{
fail_msg_writer() << "file " << m_restore_wallet << " already exists";
return false;
}
tools::password_container restore_seed_container;
if (!restore_seed_container.read_password("please, enter wallet seed phrase:\n"))
{
fail_msg_writer() << "failed to read seed phrase";
return false;
}
bool r = restore_wallet(m_restore_wallet, restore_seed_container.password(), pwd_container.password());
CHECK_AND_ASSERT_MES(r, false, "wallet restoring failed");
}
else
{
bool r = open_wallet(epee::string_encoding::convert_to_ansii(m_wallet_file), pwd_container.password());
@ -336,6 +358,7 @@ void simple_wallet::handle_command_line(const boost::program_options::variables_
m_daemon_port = command_line::get_arg(vm, arg_daemon_port);
m_do_not_set_date = command_line::get_arg(vm, arg_dont_set_date);
m_do_pos_mining = command_line::get_arg(vm, arg_do_pos_mining);
m_restore_wallet = command_line::get_arg(vm, arg_restore_wallet);
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::try_connect_to_daemon()
@ -392,6 +415,41 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::restore_wallet(const std::string &wallet_file, const std::string &restore_seed, const std::string& password)
{
m_wallet_file = wallet_file;
m_wallet.reset(new tools::wallet2());
m_wallet->callback(this->shared_from_this());
m_wallet->set_do_rise_transfer(false);
try
{
m_wallet->restore(epee::string_encoding::convert_to_unicode(wallet_file), password, restore_seed);
message_writer(epee::log_space::console_color_white, true) << "Wallet restored: " << m_wallet->get_account().get_public_address_str();
std::cout << "view key: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key) << std::endl << std::flush;
if (m_do_not_set_date)
m_wallet->reset_creation_time(0);
}
catch (const std::exception& e)
{
fail_msg_writer() << "failed to restore wallet: " << e.what();
return false;
}
m_wallet->init(m_daemon_address);
success_msg_writer() <<
"**********************************************************************\n" <<
"Your wallet has been restored.\n" <<
"To start synchronizing with the daemon use \"refresh\" command.\n" <<
"Use \"help\" command to see the list of available commands.\n" <<
"Always use \"exit\" command when closing simplewallet to save\n" <<
"current session's state. Otherwise, you will possibly need to synchronize \n" <<
"your wallet again. Your wallet key is NOT under risk anyway.\n" <<
"**********************************************************************";
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::open_wallet(const string &wallet_file, const std::string& password)
{
m_wallet_file = wallet_file;
@ -1203,6 +1261,38 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::show_seed(const std::vector<std::string> &args)
{
success_msg_writer() << "Here's your wallet's seed phrase. Write it down and keep in a safe place.";
success_msg_writer(true) << "Anyone who knows the following 25 words can access you wallet:";
std::cout << m_wallet->get_account().get_restore_braindata() << std::endl << std::flush;
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::spendkey(const std::vector<std::string> &args)
{
message_writer(epee::log_space::console_color_red, true, std::string())
<< "WARNING! Anyone who knows the following secret key can access you wallet and spend your coins.";
const account_keys& keys = m_wallet->get_account().get_keys();
std::cout << "secret: " << epee::string_tools::pod_to_hex(keys.m_spend_secret_key) << std::endl;
std::cout << "public: " << epee::string_tools::pod_to_hex(keys.m_account_address.m_spend_public_key) << std::endl << std::flush;
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::viewkey(const std::vector<std::string> &args)
{
message_writer(epee::log_space::console_color_yellow, false, std::string())
<< "WARNING! Anyone who knows the following secret key can view you wallet (but can not spend your coins).";
const account_keys& keys = m_wallet->get_account().get_keys();
std::cout << "secret: " << epee::string_tools::pod_to_hex(keys.m_view_secret_key) << std::endl;
std::cout << "public: " << epee::string_tools::pod_to_hex(keys.m_account_address.m_view_public_key) << std::endl << std::flush;
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::resync_wallet(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
m_wallet->reset_history();
@ -1461,6 +1551,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_dont_set_date);
command_line::add_arg(desc_params, arg_print_brain_wallet);
command_line::add_arg(desc_params, arg_do_pos_mining);
command_line::add_arg(desc_params, arg_restore_wallet);
command_line::add_arg(desc_params, arg_offline_mode);
command_line::add_arg(desc_params, command_line::arg_log_file);
command_line::add_arg(desc_params, command_line::arg_log_level);
@ -1597,11 +1688,6 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, arg_generate_new_wallet).size())
return EXIT_FAILURE;
if (command_line::get_arg(vm, arg_do_pos_mining))
{
message_writer(epee::log_space::console_color_magenta, true, "", 4) << "IMORTANT NOTICE! Instance started with \"do-pos-mining\" parameter, running copy of this wallet on other host at the same time may cause key image conflicts";
}
if (!offline_mode)
wal.refresh();
LOG_PRINT_GREEN("Loaded ok", LOG_LEVEL_0);

View file

@ -45,6 +45,7 @@ namespace currency
bool new_wallet(const std::string &wallet_file, const std::string& password);
bool open_wallet(const std::string &wallet_file, const std::string& password);
bool restore_wallet(const std::string &wallet_file, const std::string &restore_seed, const std::string& password);
bool close_wallet();
bool help(const std::vector<std::string> &args = std::vector<std::string>());
@ -70,6 +71,9 @@ namespace currency
bool transfer(const std::vector<std::string> &args);
bool resync_wallet(const std::vector<std::string> &args);
bool print_address(const std::vector<std::string> &args = std::vector<std::string>());
bool show_seed(const std::vector<std::string> &args);
bool spendkey(const std::vector<std::string> &args);
bool viewkey(const std::vector<std::string> &args);
bool save(const std::vector<std::string> &args);
bool set_log(const std::vector<std::string> &args);
bool enable_concole_logger(const std::vector<std::string> &args);
@ -156,6 +160,7 @@ namespace currency
bool m_print_brain_wallet;
bool m_do_pos_mining;
bool m_offline_mode;
std::string m_restore_wallet;
epee::console_handlers_binder m_cmd_binder;

View file

@ -2539,14 +2539,17 @@ bool wallet2::fill_mining_context(mining_context& ctx)
bool wallet2::try_mint_pos()
{
mining_context ctx = AUTO_VAL_INIT(ctx);
WLT_LOG_L0("Starting PoS mint iteration");
WLT_LOG_L1("Starting PoS mining iteration");
fill_mining_context(ctx);
if (!ctx.rsp.is_pos_allowed)
{
WLT_LOG_L0("POS MINING NOT ALLOWED YET");
WLT_LOG_YELLOW("POS MINING NOT ALLOWED YET", LOG_LEVEL_0);
return true;
}
WLT_LOG_L0("POS_ENTRIES: " << ctx.sp.pos_entries.size());
uint64_t pos_entries_amount = 0;
for (auto& ent : ctx.sp.pos_entries)
pos_entries_amount += ent.amount;
std::atomic<bool> stop(false);
scan_pos(ctx, stop, [this](){
@ -2564,7 +2567,8 @@ bool wallet2::try_mint_pos()
{
build_minted_block(ctx.sp, ctx.rsp);
}
WLT_LOG_L0("PoS mint iteration finished(" << ctx.rsp.status << ")");
WLT_LOG_L0("PoS mining iteration finished, status: " << ctx.rsp.status << ", used " << ctx.sp.pos_entries.size() << " entries with total amount: " << print_money_brief(pos_entries_amount));
return true;
}

View file

@ -104,6 +104,8 @@ bool wallet2::validate_escrow_proposal(const wallet_rpc::wallet_transfer_info& w
bool correct_keys = (ms.keys[0] == a_key && ms.keys[1] == b_key) || (ms.keys[0] == b_key && ms.keys[1] == a_key);
LOC_CHK(correct_keys, "template has mulisig output with invalid keys: 0:" << ms.keys[0] << " 1:" << ms.keys[1]);
LOC_CHK(cpd.amount_b_pledge + cpd.amount_to_pay > 0, "template has zero (b pledge + amount to pay)");
uint64_t min_ms_amount = cpd.amount_a_pledge + cpd.amount_b_pledge + cpd.amount_to_pay + TX_DEFAULT_FEE;
LOC_CHK(ms_amount >= min_ms_amount, "template multisig amount " << ms_amount << " is less than contract expected value: " << min_ms_amount << ", a_pledge=" << cpd.amount_a_pledge << ", b_pledge=" << cpd.amount_b_pledge << ", amount_to_pay=" << cpd.amount_to_pay);
uint64_t min_a_inputs = cpd.amount_a_pledge + cpd.amount_to_pay;

View file

@ -35,23 +35,36 @@ namespace tools
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::run(bool do_mint, bool offline_mode)
{
static const uint64_t wallet_rpt_idle_work_period_ms = 2000;
m_do_mint = do_mint;
if (!offline_mode)
{
m_net_server.add_idle_handler([this]() {
m_net_server.add_idle_handler([this]() -> bool
{
size_t blocks_fetched = 0;
bool received_money = false;
bool ok;
bool received_money = false, ok = false;
std::atomic<bool> stop(false);
LOG_PRINT_L2("wallet RPC idle: refreshing...");
m_wallet.refresh(blocks_fetched, received_money, ok, stop);
if (stop)
{
LOG_PRINT_L1("wallet RPC idle: refresh failed");
return true;
}
if (m_do_mint)
{
bool has_related_alias_in_unconfirmed = false;
LOG_PRINT_L2("wallet RPC idle: scanning tx pool...");
m_wallet.scan_tx_pool(has_related_alias_in_unconfirmed);
LOG_PRINT_L2("wallet RPC idle: tring to do PoS iteration...");
m_wallet.try_mint_pos();
}
return true;
}, 2000);
}, wallet_rpt_idle_work_period_ms);
}
//DO NOT START THIS SERVER IN MORE THEN 1 THREADS WITHOUT REFACTORING

View file

@ -115,7 +115,7 @@ namespace wallet_rpc
KV_SERIALIZE(height)
KV_SERIALIZE(unlock_time)
KV_SERIALIZE(tx_blob_size)
KV_SERIALIZE(payment_id)
KV_SERIALIZE_BLOB_AS_HEX_STRING(payment_id)
KV_SERIALIZE(remote_addresses)
KV_SERIALIZE(recipients_aliases)
KV_SERIALIZE(comment)

View file

@ -730,6 +730,7 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(escrow_cancellation_proposal_expiration);
GENERATE_AND_PLAY(escrow_cancellation_acceptance_expiration);
// GENERATE_AND_PLAY(escrow_proposal_acceptance_in_alt_chain); -- work in progress
GENERATE_AND_PLAY(escrow_zero_amounts);
GENERATE_AND_PLAY(escrow_altchain_meta_test<0>);
GENERATE_AND_PLAY(escrow_altchain_meta_test<1>);

View file

@ -1552,6 +1552,7 @@ bool escrow_custom_test::generate(std::vector<test_event_entry>& events) const
escrow_custom_test_callback_details cd = test_details[0];
cd.cpd.comment = "zero B pledge";
cd.cpd.amount_b_pledge = 0;
// note: amount to pay is not zero
test_details.push_back(cd);
}
@ -2971,3 +2972,97 @@ bool escrow_proposal_acceptance_in_alt_chain::c1(currency::core& c, size_t ev_in
//mine_next_pow_block_in_playtime()
return true;
}
//------------------------------------------------------------------------------
escrow_zero_amounts::escrow_zero_amounts()
{
REGISTER_CALLBACK_METHOD(escrow_zero_amounts, c1);
}
bool escrow_zero_amounts::generate(std::vector<test_event_entry>& events) const
{
// Try to accept contracts having (b pledge + amount to pay) == 0
// It should not be accepted by wallet (ignored), accepting such contracts is impossible
m_accounts.resize(TOTAL_ACCS_COUNT);
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate();
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate();
account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc.generate();
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
transaction tx_0 = AUTO_VAL_INIT(tx_0);
bool r = construct_tx_with_many_outputs(events, blk_0r, miner_acc.get_keys(), alice_acc.get_public_address(), MK_TEST_COINS(200), 20, TESTS_DEFAULT_FEE, tx_0);
CHECK_AND_ASSERT_MES(r, false, "construct_tx_with_many_outputs failed");
events.push_back(tx_0);
transaction tx_1 = AUTO_VAL_INIT(tx_1);
r = construct_tx_with_many_outputs(events, blk_0r, miner_acc.get_keys(), bob_acc.get_public_address(), MK_TEST_COINS(200), 20, TESTS_DEFAULT_FEE, tx_1);
CHECK_AND_ASSERT_MES(r, false, "construct_tx_with_many_outputs failed");
events.push_back(tx_1);
MAKE_NEXT_BLOCK_TX_LIST(events, blk_1, blk_0r, miner_acc, std::list<transaction>({tx_0, tx_1}));
REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
DO_CALLBACK(events, "c1");
return true;
}
bool escrow_zero_amounts::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
bool r = false;
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX);
alice_wlt->refresh();
std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, BOB_ACC_IDX);
bob_wlt->refresh();
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt, MK_TEST_COINS(200), true, UINT64_MAX, MK_TEST_COINS(200)), false, "");
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Bob", bob_wlt, MK_TEST_COINS(200), true, UINT64_MAX, MK_TEST_COINS(200)), false, "");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
// a_pledge > 0, b_pledge + amount_to_pay = 0
bc_services::contract_private_details cpd = AUTO_VAL_INIT(cpd);
cpd.amount_a_pledge = MK_TEST_COINS(10);
cpd.amount_b_pledge = 0;
cpd.amount_to_pay = 0;
cpd.a_addr = m_accounts[ALICE_ACC_IDX].get_public_address();
cpd.b_addr = m_accounts[BOB_ACC_IDX].get_public_address();
cpd.comment = get_random_text(1024);
cpd.title = get_random_text(7);
transaction proposal_tx = AUTO_VAL_INIT(proposal_tx);
transaction escrow_template_tx = AUTO_VAL_INIT(escrow_template_tx);
alice_wlt->send_escrow_proposal(cpd, 0, 0, 0, TESTS_DEFAULT_FEE, TESTS_DEFAULT_FEE, "", proposal_tx, escrow_template_tx);
crypto::hash ms_id = get_multisig_out_id(escrow_template_tx, get_multisig_out_index(escrow_template_tx.vout));
CHECK_AND_ASSERT_MES(ms_id != null_hash, false, "Can't obtain multisig id from escrow template tx");
LOG_PRINT_L0("contract 1: " << ms_id);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
bob_wlt->refresh();
bool caught = false;
try
{
bob_wlt->accept_proposal(ms_id, TESTS_DEFAULT_FEE);
}
catch (tools::error::wallet_internal_error &e)
{
LOG_PRINT_L0("caught: " << e.what());
caught = true;
}
CHECK_AND_ASSERT_MES(caught, false, "incorrect proposal was accepted");
return true;
}

View file

@ -134,3 +134,10 @@ struct escrow_proposal_acceptance_in_alt_chain : public wallet_test
bool generate(std::vector<test_event_entry>& events) const;
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
};
struct escrow_zero_amounts : public wallet_test
{
escrow_zero_amounts();
bool generate(std::vector<test_event_entry>& events) const;
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
};

View file

@ -2,10 +2,10 @@
"maj":1,
"min":0,
"rev":0,
"build":37,
"build":40,
"cs":[
{
"build":37,
"build":40,
"mode":3
}
]