forked from lthn/blockchain
cold-signing is finally working in CLI and via RPC
This commit is contained in:
parent
2c1fca9453
commit
daa01fd533
10 changed files with 331 additions and 163 deletions
|
|
@ -422,7 +422,6 @@ namespace epee
|
|||
std::string get_usage()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Commands: " << ENDL;
|
||||
size_t max_command_len = 0;
|
||||
for(auto& x:m_command_handlers)
|
||||
if(x.first.size() > max_command_len)
|
||||
|
|
@ -430,8 +429,7 @@ namespace epee
|
|||
|
||||
for(auto& x:m_command_handlers)
|
||||
{
|
||||
ss.width(max_command_len + 3);
|
||||
ss << " " << std::left << x.first << " " << x.second.second << ENDL;
|
||||
ss << " " << std::left << std::setw(max_command_len + 3) << x.first << " " << x.second.second << ENDL;
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,11 @@ namespace command_line
|
|||
|
||||
const arg_descriptor<std::string> arg_config_file = { "config-file", "Specify configuration file", std::string(CURRENCY_NAME_SHORT ".conf") };
|
||||
const arg_descriptor<bool> arg_os_version = { "os-version", "" };
|
||||
|
||||
const arg_descriptor<std::string> arg_log_dir = { "log-dir", "", "", true};
|
||||
const arg_descriptor<int> arg_log_level = { "log-level", "", LOG_LEVEL_0, true};
|
||||
const arg_descriptor<std::string> arg_log_file = { "log-file", "", "" };
|
||||
const arg_descriptor<int> arg_log_level = { "log-level", "", LOG_LEVEL_0, true };
|
||||
|
||||
const arg_descriptor<bool> arg_console = { "no-console", "Disable daemon console commands" };
|
||||
const arg_descriptor<bool> arg_show_details = { "currency-details", "Display currency details" };
|
||||
const arg_descriptor<bool> arg_show_rpc_autodoc = { "show_rpc_autodoc", "Display rpc auto-generated documentation template" };
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@ namespace command_line
|
|||
extern const arg_descriptor<std::string> arg_config_file;
|
||||
extern const arg_descriptor<bool> arg_os_version;
|
||||
extern const arg_descriptor<std::string> arg_log_dir;
|
||||
extern const arg_descriptor<std::string> arg_log_file;
|
||||
extern const arg_descriptor<int> arg_log_level;
|
||||
extern const arg_descriptor<bool> arg_console;
|
||||
extern const arg_descriptor<bool> arg_show_details;
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ namespace currency
|
|||
if (it != m_blocks_id_que.end())
|
||||
{
|
||||
//already have this block handler in que
|
||||
LOG_PRINT("Block " << block_id << " already in processing que", LOG_LEVEL_2);
|
||||
LOG_PRINT("Block " << block_id << " already in processing que", LOG_LEVEL_3);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -156,10 +156,7 @@ std::string simple_wallet::get_commands_str()
|
|||
{
|
||||
std::stringstream ss;
|
||||
ss << "Commands: " << ENDL;
|
||||
std::string usage = m_cmd_binder.get_usage();
|
||||
boost::replace_all(usage, "\n", "\n ");
|
||||
usage.insert(0, " ");
|
||||
ss << usage << ENDL;
|
||||
ss << m_cmd_binder.get_usage() << ENDL;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
|
@ -186,6 +183,7 @@ simple_wallet::simple_wallet()
|
|||
m_cmd_binder.set_handler("incoming_counts", boost::bind(&simple_wallet::show_incoming_transfers_counts, this, _1), "incoming_transfers counts");
|
||||
m_cmd_binder.set_handler("list_recent_transfers", boost::bind(&simple_wallet::list_recent_transfers, this, _1), "list_recent_transfers - Show recent maximum 1000 transfers");
|
||||
m_cmd_binder.set_handler("list_recent_transfers_ex", boost::bind(&simple_wallet::list_recent_transfers_ex, this, _1), "list_recent_transfers_tx - Write recent transfer in json to wallet_recent_transfers.txt");
|
||||
m_cmd_binder.set_handler("list_outputs", boost::bind(&simple_wallet::list_outputs, this, _1), "list_outputs [spent|unspent] - Lists all the outputs that have ever been sent to this wallet if called without arguments, otherwise it lists only the spent or unspent outputs");
|
||||
m_cmd_binder.set_handler("dump_transfers", boost::bind(&simple_wallet::dump_trunsfers, this, _1), "dump_transfers - Write transfers in json to dump_transfers.txt");
|
||||
m_cmd_binder.set_handler("dump_keyimages", boost::bind(&simple_wallet::dump_key_images, this, _1), "dump_keyimages - Write key_images in json to dump_key_images.txt");
|
||||
m_cmd_binder.set_handler("payments", boost::bind(&simple_wallet::show_payments, this, _1), "payments <payment_id_1> [<payment_id_2> ... <payment_id_N>] - Show payments <payment_id_1>, ... <payment_id_N>");
|
||||
|
|
@ -206,7 +204,9 @@ simple_wallet::simple_wallet()
|
|||
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("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_watch_only", boost::bind(&simple_wallet::save_watch_only, this, _1), "Save a watch-only keys file <filename> <password>.");
|
||||
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");
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -391,8 +391,8 @@ bool simple_wallet::open_wallet(const string &wallet_file, const std::string& pa
|
|||
try
|
||||
{
|
||||
m_wallet->load(epee::string_encoding::convert_to_unicode(m_wallet_file), password);
|
||||
message_writer(epee::log_space::console_color_white, true) << "Opened wallet: " << m_wallet->get_account().get_public_address_str();
|
||||
|
||||
message_writer(epee::log_space::console_color_white, true) << "Opened" << (m_wallet->is_watch_only() ? " watch-only" : "") << " wallet: " << m_wallet->get_account().get_public_address_str();
|
||||
|
||||
if (m_print_brain_wallet)
|
||||
std::cout << "Brain wallet: " << m_wallet->get_account().get_restore_braindata() << std::endl << std::flush;
|
||||
|
||||
|
|
@ -541,6 +541,12 @@ void simple_wallet::on_money_spent(uint64_t height, const currency::transaction&
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::refresh(const std::vector<std::string>& args)
|
||||
{
|
||||
if (m_offline_mode)
|
||||
{
|
||||
success_msg_writer() << "refresh is meaningless in OFFLINE MODE";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!try_connect_to_daemon())
|
||||
return true;
|
||||
|
||||
|
|
@ -1079,7 +1085,11 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
|
|||
currency::transaction tx;
|
||||
std::vector<extra_v> extra;
|
||||
m_wallet->transfer(dsts, fake_outs_count, 0, m_wallet->get_core_runtime_config().tx_default_fee, extra, attachments, tx);
|
||||
success_msg_writer(true) << "Money successfully sent, transaction " << get_transaction_hash(tx) << ", " << get_object_blobsize(tx) << " bytes";
|
||||
|
||||
if (!m_wallet->is_watch_only())
|
||||
success_msg_writer(true) << "Money successfully sent, transaction " << get_transaction_hash(tx) << ", " << get_object_blobsize(tx) << " bytes";
|
||||
else
|
||||
success_msg_writer(true) << "Transaction prepared for signing and saved into \"zano_tx_unsigned\" file, use full wallet to sign transfer and then use \"submit_transfer\" on this wallet to broadcast the transaction to the network";
|
||||
}
|
||||
catch (const tools::error::daemon_busy&)
|
||||
{
|
||||
|
|
@ -1162,7 +1172,12 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
|
|||
bool simple_wallet::run()
|
||||
{
|
||||
std::string addr_start = m_wallet->get_account().get_public_address_str().substr(0, 6);
|
||||
return m_cmd_binder.run_handling("[" CURRENCY_NAME_BASE " wallet " + addr_start + "]: ", "");
|
||||
std::string prompt;
|
||||
if (m_wallet->is_watch_only())
|
||||
prompt = "[" CURRENCY_NAME_BASE " WO wallet " + addr_start + "]: ";
|
||||
else
|
||||
prompt = "[" CURRENCY_NAME_BASE " wallet " + addr_start + "]: ";
|
||||
return m_cmd_binder.run_handling(prompt, "");
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void simple_wallet::stop()
|
||||
|
|
@ -1290,7 +1305,7 @@ bool simple_wallet::save_watch_only(const std::vector<std::string> &args)
|
|||
}
|
||||
try
|
||||
{
|
||||
m_wallet->store(epee::string_encoding::convert_to_unicode(args[0]), args[1], true);
|
||||
m_wallet->store_watch_only(epee::string_encoding::convert_to_unicode(args[0]), args[1]);
|
||||
success_msg_writer() << "Watch-only wallet has been stored to " << args[0];
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
|
@ -1306,6 +1321,92 @@ bool simple_wallet::save_watch_only(const std::vector<std::string> &args)
|
|||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::list_outputs(const std::vector<std::string> &args)
|
||||
{
|
||||
if (args.size() > 1)
|
||||
{
|
||||
fail_msg_writer() << "invalid syntax: one or none parameters are expected, " << args.size() << " was given";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool include_spent = true, include_unspent = true;
|
||||
if (args.size() == 1)
|
||||
{
|
||||
if (args[0] == "unspent" || args[0] == "available")
|
||||
include_spent = false;
|
||||
else if (args[0] == "spent" || args[0] == "unavailable")
|
||||
include_unspent = false;
|
||||
else
|
||||
{
|
||||
fail_msg_writer() << "invalid parameter: " << args[0];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
success_msg_writer() << "list of all the outputs that have ever been sent to this wallet:" << ENDL <<
|
||||
m_wallet->get_transfers_str(include_spent, include_unspent);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::sign_transfer(const std::vector<std::string> &args)
|
||||
{
|
||||
if (m_wallet->is_watch_only())
|
||||
{
|
||||
fail_msg_writer() << "You can't sign transaction in watch-only wallet";
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
if (args.size() < 2)
|
||||
{
|
||||
fail_msg_writer() << "wrong parameters, expected: <unsigned_tx_file> <signed_tx_file>";
|
||||
return true;
|
||||
}
|
||||
try
|
||||
{
|
||||
currency::transaction res_tx;
|
||||
m_wallet->sign_transfer_files(args[0], args[1], res_tx);
|
||||
success_msg_writer(true) << "transaction signed and stored to file: " << args[1] << ", transaction " << get_transaction_hash(res_tx) << ", " << get_object_blobsize(res_tx) << " bytes";
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG_ERROR("unexpected error: " << e.what());
|
||||
fail_msg_writer() << "unexpected error: " << e.what();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_ERROR("Unknown error");
|
||||
fail_msg_writer() << "unknown error";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::submit_transfer(const std::vector<std::string> &args)
|
||||
{
|
||||
if (args.size() < 1)
|
||||
{
|
||||
fail_msg_writer() << "wrong parameters, expected filename";
|
||||
return true;
|
||||
}
|
||||
try
|
||||
{
|
||||
currency::transaction res_tx;
|
||||
m_wallet->submit_transfer_files(args[0], res_tx);
|
||||
success_msg_writer(true) << "transaction " << get_transaction_hash(res_tx) << " was successfully sent, size: " << get_object_blobsize(res_tx) << " bytes";
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG_ERROR("unexpected error: " << e.what());
|
||||
fail_msg_writer() << "unexpected error: " << e.what();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_ERROR("Unknown error");
|
||||
fail_msg_writer() << "unknown error";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
|
@ -1341,6 +1442,8 @@ int main(int argc, char* argv[])
|
|||
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_offline_mode);
|
||||
command_line::add_arg(desc_params, command_line::arg_log_file);
|
||||
command_line::add_arg(desc_params, command_line::arg_log_level);
|
||||
|
||||
|
||||
tools::wallet_rpc_server::init_options(desc_params);
|
||||
|
|
@ -1378,17 +1481,24 @@ int main(int argc, char* argv[])
|
|||
|
||||
//set up logging options
|
||||
log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2);
|
||||
log_space::log_singletone::add_logger(LOGGER_FILE,
|
||||
log_space::log_singletone::get_default_log_file().c_str(),
|
||||
log_space::log_singletone::get_default_log_folder().c_str(), LOG_LEVEL_4);
|
||||
|
||||
boost::filesystem::path log_file_path(command_line::get_arg(vm, command_line::arg_log_file));
|
||||
if (log_file_path.empty())
|
||||
log_file_path = log_space::log_singletone::get_default_log_file();
|
||||
std::string log_dir;
|
||||
log_dir = log_file_path.has_parent_path() ? log_file_path.parent_path().string() : log_space::log_singletone::get_default_log_folder();
|
||||
log_space::log_singletone::add_logger(LOGGER_FILE, log_file_path.filename().string().c_str(), log_dir.c_str(), LOG_LEVEL_4);
|
||||
message_writer(epee::log_space::console_color_white, true) << CURRENCY_NAME << " wallet v" << PROJECT_VERSION_LONG;
|
||||
|
||||
if(command_line::has_arg(vm, arg_log_level))
|
||||
if (command_line::has_arg(vm, arg_log_level))
|
||||
{
|
||||
LOG_PRINT_L0("Setting log level = " << command_line::get_arg(vm, arg_log_level));
|
||||
log_space::get_set_log_detalisation_level(true, command_line::get_arg(vm, arg_log_level));
|
||||
}
|
||||
if (command_line::has_arg(vm, command_line::arg_log_level))
|
||||
{
|
||||
LOG_PRINT_L0("Setting log level = " << command_line::get_arg(vm, command_line::arg_log_level));
|
||||
log_space::get_set_log_detalisation_level(true, command_line::get_arg(vm, command_line::arg_log_level));
|
||||
}
|
||||
|
||||
bool offline_mode = command_line::get_arg(vm, arg_offline_mode);
|
||||
|
||||
|
|
@ -1479,7 +1589,7 @@ int main(int argc, char* argv[])
|
|||
wrpc.send_stop_signal();
|
||||
});
|
||||
LOG_PRINT_L0("Starting wallet rpc server");
|
||||
wrpc.run(command_line::get_arg(vm, arg_do_pos_mining) );
|
||||
wrpc.run(command_line::get_arg(vm, arg_do_pos_mining), offline_mode);
|
||||
LOG_PRINT_L0("Stopped wallet rpc server");
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ namespace currency
|
|||
bool dump_key_images(const std::vector<std::string>& args);
|
||||
bool show_incoming_transfers(const std::vector<std::string> &args);
|
||||
bool show_incoming_transfers_counts(const std::vector<std::string> &args);
|
||||
bool list_outputs(const std::vector<std::string> &args);
|
||||
bool show_payments(const std::vector<std::string> &args);
|
||||
bool get_transfer_info(const std::vector<std::string> &args);
|
||||
bool scan_for_key_image_collisions(const std::vector<std::string> &args);
|
||||
|
|
@ -75,6 +76,8 @@ namespace currency
|
|||
bool integrated_address(const std::vector<std::string> &args);
|
||||
bool get_tx_key(const std::vector<std::string> &args_);
|
||||
bool save_watch_only(const std::vector<std::string> &args);
|
||||
bool sign_transfer(const std::vector<std::string> &args);
|
||||
bool submit_transfer(const std::vector<std::string> &args);
|
||||
|
||||
bool get_alias_from_daemon(const std::string& alias_name, currency::extra_alias_entry_base& ai);
|
||||
bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,22 @@ void wallet2::fill_transfer_details(const currency::transaction& tx, const tools
|
|||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::transfer_flags_to_str(uint32_t flags)
|
||||
{
|
||||
std::string result(5, ' ');
|
||||
if (flags & WALLET_TRANSFER_DETAIL_FLAG_SPENT)
|
||||
result[0] = 's';
|
||||
if (flags & WALLET_TRANSFER_DETAIL_FLAG_BLOCKED)
|
||||
result[1] = 'b';
|
||||
if (flags & WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION)
|
||||
result[2] = 'e';
|
||||
if (flags & WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER)
|
||||
result[3] = 'm';
|
||||
if (flags & WALLET_TRANSFER_DETAIL_FLAG_COLD_SIG_RESERVATION)
|
||||
result[4] = 'c';
|
||||
return result;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::transform_tx_to_str(const currency::transaction& tx)
|
||||
{
|
||||
return currency::obj_to_json_str(tx);
|
||||
|
|
@ -327,7 +343,6 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
td.m_internal_output_index = o;
|
||||
td.m_key_image = ki;
|
||||
td.m_global_output_index = res.o_indexes[o];
|
||||
td.m_flags &= ~(WALLET_TRANSFER_DETAIL_FLAG_SPENT);
|
||||
if (coin_base_tx)
|
||||
{
|
||||
//last out in coinbase tx supposed to be change from coinstake
|
||||
|
|
@ -349,7 +364,6 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
transfer_details_base& tdb = m_multisig_transfers[multisig_id];
|
||||
tdb.m_ptx_wallet_info = pwallet_info;
|
||||
tdb.m_internal_output_index = o;
|
||||
tdb.m_flags &= ~(WALLET_TRANSFER_DETAIL_FLAG_SPENT);
|
||||
WLT_LOG_L0("Received multisig, multisig out id: " << multisig_id << ", amount: " << tdb.amount() << ", with tx: " << get_transaction_hash(tx));
|
||||
}
|
||||
}
|
||||
|
|
@ -1823,7 +1837,7 @@ void wallet2::load_keys2ki(bool create_if_not_exist, bool& need_to_resync)
|
|||
{
|
||||
WLT_LOG_RED("m_pending_key_images size: " << m_pending_key_images.size() << " is GREATER than m_pending_key_images_file_container size: " << m_pending_key_images_file_container.size(), LOG_LEVEL_0);
|
||||
WLT_LOG_RED("UNRECOVERABLE ERROR, wallet stops", LOG_LEVEL_0);
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(false, "m_pending_key_images > m_pending_key_images_file_container");
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(false, "UNRECOVERABLE ERROR, wallet stops: m_pending_key_images > m_pending_key_images_file_container");
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
@ -1958,20 +1972,18 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password)
|
|||
THROW_IF_TRUE_WALLET_EX(need_to_resync, error::wallet_load_notice_wallet_restored, epee::string_encoding::convert_to_ansii(m_wallet_file));
|
||||
|
||||
WLT_LOG_L0("Loaded wallet file" << (m_watch_only ? " (WATCH ONLY) " : " ") << string_encoding::convert_to_ansii(m_wallet_file) << " with public address: " << m_account.get_public_address_str());
|
||||
WLT_LOG_L0("(pending_key_images: " << m_pending_key_images.size() << ", pki file elements: " << m_pending_key_images_file_container.size() << ", tx_keys: " << m_tx_keys.size() << ")");
|
||||
WLT_LOG_L0("(after loading: pending_key_images: " << m_pending_key_images.size() << ", pki file elements: " << m_pending_key_images_file_container.size() << ", tx_keys: " << m_tx_keys.size() << ")");
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::store()
|
||||
{
|
||||
store(m_wallet_file, m_password, false);
|
||||
store(m_wallet_file, m_password);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::store(const std::wstring& path_to_save, const std::string& password, bool store_as_watch_only)
|
||||
void wallet2::store(const std::wstring& path_to_save, const std::string& password)
|
||||
{
|
||||
LOG_PRINT_L0("(before storing: pending_key_images: " << m_pending_key_images.size() << ", pki file elements: " << m_pending_key_images_file_container.size() << ", tx_keys: " << m_tx_keys.size() << ")");
|
||||
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(!(store_as_watch_only && path_to_save == m_wallet_file), "ttrying to save watch-only wallet to the same wallet file!");
|
||||
|
||||
//prepare data
|
||||
std::string keys_buff;
|
||||
bool r = store_keys(keys_buff, password);
|
||||
|
|
@ -1996,22 +2008,58 @@ void wallet2::store(const std::wstring& path_to_save, const std::string& passwor
|
|||
data_file << header_buff << keys_buff;
|
||||
WLT_LOG_L0("Storing to file...");
|
||||
|
||||
if (store_as_watch_only)
|
||||
{
|
||||
// TODO
|
||||
r = tools::portble_serialize_obj_to_stream(*this, data_file);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "failed to portble_serialize_obj_to_stream for wallet " << epee::string_encoding::convert_to_ansii(m_wallet_file));
|
||||
}
|
||||
else
|
||||
{
|
||||
r = tools::portble_serialize_obj_to_stream(*this, data_file);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "failed to portble_serialize_obj_to_stream for wallet " << epee::string_encoding::convert_to_ansii(m_wallet_file));
|
||||
}
|
||||
r = tools::portble_serialize_obj_to_stream(*this, data_file);
|
||||
CHECK_AND_ASSERT_THROW_MES(r, "failed to portble_serialize_obj_to_stream for wallet " << epee::string_encoding::convert_to_ansii(m_wallet_file));
|
||||
|
||||
data_file.flush();
|
||||
data_file.close();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::store_watch_only(const std::wstring& path_to_save, const std::string& password) const
|
||||
{
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(path_to_save != m_wallet_file, "trying to save watch-only wallet to the same wallet file!");
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(!m_watch_only, "saving watch-only wallet into a watch-only wallet is not allowed");
|
||||
|
||||
// prepare data for watch-only wallet
|
||||
wallet2 wo;
|
||||
// wallet2 wo(*this); copy-constructor is not working, so do a this serialization workaround
|
||||
std::stringstream stream_buffer;
|
||||
tools::portble_serialize_obj_to_stream(*this, stream_buffer);
|
||||
tools::portable_unserialize_obj_from_stream(wo, stream_buffer);
|
||||
|
||||
wo.m_watch_only = true;
|
||||
wo.m_account = m_account;
|
||||
wo.m_account.make_account_watch_only();
|
||||
wo.prepare_file_names(path_to_save);
|
||||
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(!boost::filesystem::exists(wo.m_wallet_file), "file " << epee::string_encoding::convert_to_ansii(wo.m_wallet_file) << " already exists");
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(!boost::filesystem::exists(wo.m_pending_ki_file), "file " << epee::string_encoding::convert_to_ansii(wo.m_pending_ki_file) << " already exists");
|
||||
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(wo.m_pending_key_images.empty(), "pending key images is expected to be empty");
|
||||
bool stub = false;
|
||||
wo.load_keys2ki(true, stub); // to create outkey2ki file
|
||||
|
||||
// populate pending key images for spent outputs (this will help to resync watch-only wallet)
|
||||
for (size_t ti = 0; ti < wo.m_transfers.size(); ++ti)
|
||||
{
|
||||
const auto& td = wo.m_transfers[ti];
|
||||
if (!td.is_spent())
|
||||
continue; // only spent transfers really need to be stored, because watch-only wallet will not be able to figure out they were spent otherwise
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_internal_output_index < td.m_ptx_wallet_info->m_tx.vout.size(), "invalid transfer #" << ti);
|
||||
const currency::txout_target_v& out_t = td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target;
|
||||
if (out_t.type() != typeid(currency::txout_to_key))
|
||||
continue;
|
||||
const crypto::public_key& out_key = boost::get<txout_to_key>(out_t).key;
|
||||
wo.m_pending_key_images.insert(std::make_pair(out_key, td.m_key_image));
|
||||
wo.m_pending_key_images_file_container.push_back(tools::out_key_to_ki(out_key, td.m_key_image));
|
||||
WLT_LOG_L1("preparing watch-only wallet: added pending ki (" << out_key << ", " << td.m_key_image << ")");
|
||||
}
|
||||
|
||||
// TODO additional clearing for watch-only wallet's data
|
||||
|
||||
wo.store(path_to_save, password);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::unlocked_balance() const
|
||||
{
|
||||
uint64_t stub = 0;
|
||||
|
|
@ -2044,7 +2092,7 @@ uint64_t wallet2::balance(uint64_t& unloked, uint64_t& awaiting_in, uint64_t& aw
|
|||
|
||||
for(auto& td : m_transfers)
|
||||
{
|
||||
if (!td.is_spent())
|
||||
if (td.is_spendable())
|
||||
{
|
||||
balance_total += td.amount();
|
||||
if (is_transfer_unlocked(td))
|
||||
|
|
@ -2100,18 +2148,6 @@ uint64_t wallet2::balance(uint64_t& unloked, uint64_t& awaiting_in, uint64_t& aw
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet2::balance() const
|
||||
{
|
||||
// uint64_t amount = 0;
|
||||
// BOOST_FOREACH(auto& td, m_transfers)
|
||||
// if(!td.m_spent)
|
||||
// amount += td.amount();
|
||||
//
|
||||
//
|
||||
// BOOST_FOREACH(auto& utx, m_unconfirmed_txs)
|
||||
// if (utx.second.is_income)
|
||||
// amount+= utx.second.amount;
|
||||
//
|
||||
// return amount;
|
||||
|
||||
uint64_t stub = 0;
|
||||
return balance(stub, stub, stub, stub);
|
||||
}
|
||||
|
|
@ -2121,6 +2157,37 @@ void wallet2::get_transfers(wallet2::transfer_container& incoming_transfers) con
|
|||
incoming_transfers = m_transfers;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool include_unspent /*= true*/) const
|
||||
{
|
||||
static const char* header = "index amount g_index flags block tx out# key image";
|
||||
std::stringstream ss;
|
||||
ss << header << ENDL;
|
||||
size_t count = 0;
|
||||
for (size_t i = 0; i != m_transfers.size(); ++i)
|
||||
{
|
||||
const transfer_details& td = m_transfers[i];
|
||||
|
||||
if ((td.is_spent() && !include_spent) || (!td.is_spent() && !include_unspent))
|
||||
continue;
|
||||
|
||||
ss << std::right <<
|
||||
std::setw(5) << i << " " <<
|
||||
std::setw(21) << print_money(td.amount()) << " " <<
|
||||
std::setw(7) << td.m_global_output_index << " " <<
|
||||
std::setw(2) << std::setfill('0') << td.m_flags << std::setfill(' ') << ":" <<
|
||||
std::setw(5) << transfer_flags_to_str(td.m_flags) << " " <<
|
||||
std::setw(7) << td.m_ptx_wallet_info->m_block_height << " " <<
|
||||
get_transaction_hash(td.m_ptx_wallet_info->m_tx) << " " <<
|
||||
std::setw(4) << td.m_internal_output_index << " " <<
|
||||
td.m_key_image << ENDL;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
ss << "printed " << count << " outputs of " << m_transfers.size() << " total" << ENDL;
|
||||
return ss.str();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::get_payments(const std::string& payment_id, std::list<wallet2::payment_details>& payments, uint64_t min_height) const
|
||||
{
|
||||
auto range = m_payments.equal_range(payment_id);
|
||||
|
|
@ -2141,16 +2208,14 @@ void wallet2::sign_transfer(const std::string& tx_sources_blob, std::string& sig
|
|||
// decrypt the blob
|
||||
std::string decrypted_src_blob = crypto::chacha_crypt(tx_sources_blob, m_account.get_keys().m_view_secret_key);
|
||||
|
||||
// deserialize create_tx_arg
|
||||
construct_tx_param ctp = AUTO_VAL_INIT(ctp);
|
||||
bool r = t_unserializable_object_from_blob(ctp, decrypted_src_blob);
|
||||
// deserialize args
|
||||
finalized_tx ft = AUTO_VAL_INIT(ft);
|
||||
bool r = t_unserializable_object_from_blob(ft.ftp, decrypted_src_blob);
|
||||
THROW_IF_FALSE_WALLET_EX(r, error::wallet_common_error, "Failed to decrypt tx sources blob");
|
||||
|
||||
// make sure unsigned tx was created with the same keys
|
||||
THROW_IF_FALSE_WALLET_EX(ctp.spend_pub_key == m_account.get_keys().m_account_address.m_spend_public_key, error::wallet_common_error, "The tx sources was created in a different wallet, keys missmatch");
|
||||
THROW_IF_FALSE_WALLET_EX(ft.ftp.spend_pub_key == m_account.get_keys().m_account_address.m_spend_public_key, error::wallet_common_error, "The was created in a different wallet, keys missmatch");
|
||||
|
||||
finalized_tx ft = AUTO_VAL_INIT(ft);
|
||||
prepare_transaction(ctp, ft.ftp);
|
||||
finalize_transaction(ft.ftp, ft.tx, ft.one_time_key, false);
|
||||
|
||||
// calculate key images for each change output
|
||||
|
|
@ -2186,19 +2251,21 @@ void wallet2::sign_transfer(const std::string& tx_sources_blob, std::string& sig
|
|||
// serialize and encrypt the result
|
||||
signed_tx_blob = t_serializable_object_to_blob(ft);
|
||||
crypto::chacha_crypt(signed_tx_blob, m_account.get_keys().m_view_secret_key);
|
||||
|
||||
tx = ft.tx;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::sign_transfer_files(const std::string& tx_sources_file, const std::string& signed_tx_file, currency::transaction& tx)
|
||||
{
|
||||
std::string sources_blob;
|
||||
bool r = epee::file_io_utils::load_file_to_string(tx_sources_file, sources_blob);
|
||||
THROW_IF_FALSE_WALLET_EX(r, error::wallet_common_error, std::string("failed to open file ") + tx_sources_file);
|
||||
THROW_IF_FALSE_WALLET_CMN_ERR_EX(r, "failed to open file " << tx_sources_file);
|
||||
|
||||
std::string signed_tx_blob;
|
||||
sign_transfer(sources_blob, signed_tx_blob, tx);
|
||||
|
||||
r = epee::file_io_utils::save_string_to_file(signed_tx_file, signed_tx_blob);
|
||||
THROW_IF_FALSE_WALLET_EX(r, error::wallet_common_error, std::string("failed to store signed tx to file ") + signed_tx_file);
|
||||
THROW_IF_FALSE_WALLET_CMN_ERR_EX(r, "failed to store signed tx to file " << signed_tx_file);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::submit_transfer(const std::string& signed_tx_blob, currency::transaction& tx)
|
||||
|
|
@ -2209,22 +2276,26 @@ void wallet2::submit_transfer(const std::string& signed_tx_blob, currency::trans
|
|||
// deserialize tx data
|
||||
finalized_tx ft = AUTO_VAL_INIT(ft);
|
||||
bool r = t_unserializable_object_from_blob(ft, decrypted_src_blob);
|
||||
THROW_IF_FALSE_WALLET_EX(r, error::wallet_common_error, "Failed to decrypt tx sources blob");
|
||||
THROW_IF_FALSE_WALLET_EX(r, error::wallet_common_error, "Failed to decrypt signed tx data");
|
||||
tx = ft.tx;
|
||||
crypto::hash tx_hash = get_transaction_hash(tx);
|
||||
|
||||
crypto::hash tx_hash = get_transaction_hash(ft.tx);
|
||||
// foolproof
|
||||
THROW_IF_FALSE_WALLET_CMN_ERR_EX(ft.ftp.spend_pub_key == m_account.get_keys().m_account_address.m_spend_public_key, "The given tx was created in a different wallet, keys missmatch, tx hash: " << tx_hash);
|
||||
|
||||
try
|
||||
{
|
||||
send_transaction_to_network(ft.tx);
|
||||
send_transaction_to_network(tx);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// clear spent transfers if smth went wrong
|
||||
clear_transfers_from_flag(ft.ftp.selected_transfers, WALLET_TRANSFER_DETAIL_FLAG_SPENT, "broadcasting tx " + epee::string_tools::pod_to_hex(tx_hash) + " was unsuccessful");
|
||||
// clear transfers flags if smth went wrong
|
||||
uint32_t flag = WALLET_TRANSFER_DETAIL_FLAG_SPENT | WALLET_TRANSFER_DETAIL_FLAG_COLD_SIG_RESERVATION;
|
||||
clear_transfers_from_flag(ft.ftp.selected_transfers, flag, "broadcasting tx " + epee::string_tools::pod_to_hex(tx_hash) + " was unsuccessful");
|
||||
throw;
|
||||
}
|
||||
|
||||
add_sent_tx_detailed_info(ft.tx, ft.ftp.prepared_destinations, ft.ftp.selected_transfers);
|
||||
add_sent_tx_detailed_info(tx, ft.ftp.prepared_destinations, ft.ftp.selected_transfers);
|
||||
m_tx_keys.insert(std::make_pair(tx_hash, ft.one_time_key));
|
||||
|
||||
if (m_watch_only)
|
||||
|
|
@ -2286,7 +2357,7 @@ void wallet2::submit_transfer(const std::string& signed_tx_blob, currency::trans
|
|||
}
|
||||
|
||||
// TODO: print inputs' key images
|
||||
print_tx_sent_message(ft.tx, "(from submit_transfer)");
|
||||
print_tx_sent_message(tx, "(from submit_transfer)");
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::submit_transfer_files(const std::string& signed_tx_file, currency::transaction& tx)
|
||||
|
|
@ -2323,7 +2394,7 @@ bool wallet2::get_transfer_address(const std::string& adr_str, currency::account
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::is_transfer_okay_for_pos(const transfer_details& tr)
|
||||
{
|
||||
if (tr.m_flags & WALLET_TRANSFER_DETAIL_FLAG_SPENT)
|
||||
if (!tr.is_spendable())
|
||||
return false;
|
||||
|
||||
//blockchain conditions
|
||||
|
|
@ -3339,11 +3410,19 @@ void wallet2::add_sent_tx_detailed_info(const transaction& tx,
|
|||
add_sent_unconfirmed_tx(tx, recipients, selected_transfers, destinations);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::mark_transfers_with_flag(const std::vector<uint64_t>& selected_transfers, uint32_t flag, const std::string& reason /* = empty_string */)
|
||||
void wallet2::mark_transfers_with_flag(const std::vector<uint64_t>& selected_transfers, uint32_t flag, const std::string& reason /* = empty_string */, bool throw_if_flag_already_set /* = false */)
|
||||
{
|
||||
if (throw_if_flag_already_set)
|
||||
{
|
||||
for (uint64_t i : selected_transfers)
|
||||
{
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(i < m_transfers.size(), "invalid transfer index given: " << i << ", m_transfers.size() == " << m_transfers.size());
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX((m_transfers[i].m_flags & flag) == 0, "transfer #" << i << " already has flag " << flag << ": " << m_transfers[i].m_flags << ", transfer info:" << ENDL << epee::serialization::store_t_to_json(m_transfers[i]));
|
||||
}
|
||||
}
|
||||
for (uint64_t i : selected_transfers)
|
||||
{
|
||||
THROW_IF_TRUE_WALLET_EX(i >= m_transfers.size(), error::wallet_internal_error, "i >= m_transfers.size()");
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(i < m_transfers.size(), "invalid transfer index given: " << i << ", m_transfers.size() == " << m_transfers.size());
|
||||
uint32_t flags_before = m_transfers[i].m_flags;
|
||||
m_transfers[i].m_flags |= flag;
|
||||
WLT_LOG_L1("marking transfer #" << std::setfill('0') << std::right << std::setw(3) << i << " with flag " << flag << " : " << flags_before << " -> " << m_transfers[i].m_flags <<
|
||||
|
|
@ -3368,6 +3447,12 @@ void wallet2::exception_handler()
|
|||
m_found_free_amounts.clear();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::exception_handler() const
|
||||
{
|
||||
// do nothing
|
||||
// TODO: is it correct?
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::mark_transfers_as_spent(const std::vector<uint64_t>& selected_transfers, const std::string& reason /* = empty_string */)
|
||||
{
|
||||
// TODO: design a safe undo for this operation
|
||||
|
|
@ -3535,12 +3620,13 @@ bool wallet2::is_transfer_ready_to_go(const transfer_details& td, uint64_t fake_
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::is_transfer_able_to_go(const transfer_details& td, uint64_t fake_outputs_count)
|
||||
{
|
||||
if (!static_cast<bool>(td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_SPENT)
|
||||
&& currency::is_mixattr_applicable_for_fake_outs_counter(boost::get<currency::txout_to_key>(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target).mix_attr, fake_outputs_count))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (!td.is_spendable())
|
||||
return false;
|
||||
|
||||
if (!currency::is_mixattr_applicable_for_fake_outs_counter(boost::get<currency::txout_to_key>(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target).mix_attr, fake_outputs_count))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_free_transfers_cache(uint64_t fake_outputs_count)
|
||||
|
|
@ -3898,22 +3984,6 @@ void wallet2::transfer(const std::vector<currency::tx_destination_entry>& dsts,
|
|||
transfer(dsts, fake_outputs_count, unlock_time, fee, extra, attachments, destination_split_strategy_id, dust_policy, tx);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
tx workflow:
|
||||
|
||||
prepare_transaction(construct_param, construct_res, tools::detail::digit_split_strategy);
|
||||
mark_transfers_as_spent(construct_res.selected_transfers, std::string("contract <") + epee::string_tools::pod_to_hex(contract_id) + "> has been accepted with tx <" + epee::string_tools::pod_to_hex(get_transaction_hash(construct_res.tx)) + ">");
|
||||
--
|
||||
store/load
|
||||
--
|
||||
finalize_transaction()
|
||||
construct_tx
|
||||
sign ms input
|
||||
send_transaction_to_network(construct_res.tx);
|
||||
add_sent_tx_detailed_info(construct_res.tx, construct_res.prepared_destinations, construct_res.selected_transfers);
|
||||
print_tx_sent_message(construct_res.tx, "(contract)", construct_param.fee);
|
||||
*/
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::transfer(const std::vector<currency::tx_destination_entry>& dsts,
|
||||
size_t fake_outputs_count,
|
||||
uint64_t unlock_time,
|
||||
|
|
@ -3930,34 +4000,34 @@ void wallet2::transfer(const std::vector<currency::tx_destination_entry>& dsts,
|
|||
std::string* p_signed_tx_blob_str)
|
||||
{
|
||||
TIME_MEASURE_START(precalculation_time);
|
||||
construct_tx_param tx_param = AUTO_VAL_INIT(tx_param);
|
||||
tx_param.attachments = attachments;
|
||||
tx_param.crypt_address = currency::get_crypt_address_from_destinations(m_account.get_keys(), dsts);
|
||||
tx_param.dsts = dsts;
|
||||
tx_param.dust_policy = dust_policy;
|
||||
tx_param.extra = extra;
|
||||
tx_param.fake_outputs_count = fake_outputs_count;
|
||||
tx_param.fee = fee;
|
||||
tx_param.flags = flags;
|
||||
// tx_param.mark_tx_as_complete
|
||||
// tx_param.multisig_id
|
||||
tx_param.shuffle = shuffle;
|
||||
tx_param.split_strategy_id = destination_split_strategy_id;
|
||||
tx_param.tx_outs_attr = tx_outs_attr;
|
||||
tx_param.unlock_time = unlock_time;
|
||||
construct_tx_param ctp = AUTO_VAL_INIT(ctp);
|
||||
ctp.attachments = attachments;
|
||||
ctp.crypt_address = currency::get_crypt_address_from_destinations(m_account.get_keys(), dsts);
|
||||
ctp.dsts = dsts;
|
||||
ctp.dust_policy = dust_policy;
|
||||
ctp.extra = extra;
|
||||
ctp.fake_outputs_count = fake_outputs_count;
|
||||
ctp.fee = fee;
|
||||
ctp.flags = flags;
|
||||
// ctp.mark_tx_as_complete
|
||||
// ctp.multisig_id
|
||||
ctp.shuffle = shuffle;
|
||||
ctp.split_strategy_id = destination_split_strategy_id;
|
||||
ctp.tx_outs_attr = tx_outs_attr;
|
||||
ctp.unlock_time = unlock_time;
|
||||
TIME_MEASURE_FINISH(precalculation_time);
|
||||
|
||||
TIME_MEASURE_START(prepare_transaction_time);
|
||||
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
|
||||
prepare_transaction(tx_param, ftp);
|
||||
prepare_transaction(ctp, ftp);
|
||||
TIME_MEASURE_FINISH(prepare_transaction_time);
|
||||
|
||||
if (m_watch_only)
|
||||
{
|
||||
tx_param.spend_pub_key = m_account.get_public_address().m_spend_public_key;
|
||||
blobdata bl = t_serializable_object_to_blob(tx_param);
|
||||
ftp.spend_pub_key = m_account.get_public_address().m_spend_public_key;
|
||||
blobdata bl = t_serializable_object_to_blob(ftp);
|
||||
crypto::chacha_crypt(bl, m_account.get_keys().m_view_secret_key);
|
||||
epee::file_io_utils::save_string_to_file("unsigned_zano_tx", bl);
|
||||
epee::file_io_utils::save_string_to_file("zano_tx_unsigned", bl);
|
||||
LOG_PRINT_L0("Transaction stored to unsigned_zano_tx. You need to sign this tx using a full-access wallet.");
|
||||
|
||||
if (p_signed_tx_blob_str != nullptr)
|
||||
|
|
@ -3965,7 +4035,7 @@ void wallet2::transfer(const std::vector<currency::tx_destination_entry>& dsts,
|
|||
|
||||
// unlock transfers at the very end
|
||||
TIME_MEASURE_START(mark_transfers_as_spent_time);
|
||||
mark_transfers_as_spent(ftp.selected_transfers, std::string("money transfer"));
|
||||
mark_transfers_with_flag(ftp.selected_transfers, WALLET_TRANSFER_DETAIL_FLAG_COLD_SIG_RESERVATION, std::string("cold sig reservation for money transfer"), true);
|
||||
TIME_MEASURE_FINISH(mark_transfers_as_spent_time);
|
||||
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -254,37 +254,10 @@ namespace tools
|
|||
currency::account_public_address crypt_address;
|
||||
uint8_t tx_outs_attr;
|
||||
bool shuffle;
|
||||
|
||||
crypto::public_key spend_pub_key; // only for validations
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(dsts)
|
||||
FIELD(fake_outputs_count)
|
||||
FIELD(fee)
|
||||
FIELD(dust_policy)
|
||||
FIELD(multisig_id)
|
||||
FIELD(flags)
|
||||
FIELD(split_strategy_id)
|
||||
FIELD(mark_tx_as_complete)
|
||||
FIELD(unlock_time)
|
||||
FIELD(extra)
|
||||
FIELD(attachments)
|
||||
FIELD(crypt_address)
|
||||
FIELD(tx_outs_attr)
|
||||
FIELD(shuffle)
|
||||
FIELD(spend_pub_key)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct finalize_tx_param
|
||||
{
|
||||
//std::vector<currency::tx_destination_entry> dsts;
|
||||
//size_t fake_outputs_count;
|
||||
//uint64_t fee;
|
||||
//tx_dust_policy dust_policy;
|
||||
//bool mark_tx_as_complete;
|
||||
//detail::split_strategy_id_t split_strategy_id;
|
||||
|
||||
uint64_t unlock_time;
|
||||
std::vector<currency::extra_v> extra;
|
||||
std::vector<currency::attachment_v> attachments;
|
||||
|
|
@ -354,11 +327,13 @@ namespace tools
|
|||
m_core_runtime_config = currency::get_default_core_runtime_config();
|
||||
};
|
||||
|
||||
#define WALLET_TRANSFER_DETAIL_FLAG_SPENT 0x00000001
|
||||
#define WALLET_TRANSFER_DETAIL_FLAG_BLOCKED 0x00000002
|
||||
#define WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION 0x00000004
|
||||
#define WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER 0x00000008
|
||||
|
||||
#define WALLET_TRANSFER_DETAIL_FLAG_SPENT uint32_t(1 << 0)
|
||||
#define WALLET_TRANSFER_DETAIL_FLAG_BLOCKED uint32_t(1 << 1)
|
||||
#define WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION uint32_t(1 << 2)
|
||||
#define WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER uint32_t(1 << 3)
|
||||
#define WALLET_TRANSFER_DETAIL_FLAG_COLD_SIG_RESERVATION uint32_t(1 << 4) // transfer is reserved for cold-signing (unsigned tx was created and passed for signing)
|
||||
|
||||
static std::string transfer_flags_to_str(uint32_t flags);
|
||||
static std::string transform_tx_to_str(const currency::transaction& tx);
|
||||
static currency::transaction transform_str_to_tx(const std::string& tx_str);
|
||||
|
||||
|
|
@ -393,9 +368,9 @@ namespace tools
|
|||
|
||||
uint64_t amount() const { return m_ptx_wallet_info->m_tx.vout[m_internal_output_index].amount; }
|
||||
bool is_spent() const { return m_flags & WALLET_TRANSFER_DETAIL_FLAG_SPENT; }
|
||||
bool is_spendable() const { return (m_flags & (~WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER)) == 0; } // spenable = has no flags or mined flag only
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
//KV_SERIALIZE(*m_ptx_wallet_info)
|
||||
KV_SERIALIZE_CUSTOM(m_ptx_wallet_info, const transaction_wallet_info&, tools::wallet2::transform_ptr_to_value, tools::wallet2::transform_value_to_ptr)
|
||||
KV_SERIALIZE(m_internal_output_index)
|
||||
KV_SERIALIZE(m_spent_height)
|
||||
|
|
@ -471,7 +446,8 @@ namespace tools
|
|||
void restore(const std::wstring& path, const std::string& pass, const std::string& restore_key);
|
||||
void load(const std::wstring& wallet, const std::string& password);
|
||||
void store();
|
||||
void store(const std::wstring& path, const std::string& password, bool store_as_watch_only = false);
|
||||
void store(const std::wstring& path, const std::string& password);
|
||||
void store_watch_only(const std::wstring& path, const std::string& password) const;
|
||||
bool store_keys(std::string& buff, const std::string& password, bool store_as_watch_only = false);
|
||||
std::wstring get_wallet_path(){ return m_wallet_file; }
|
||||
currency::account_base& get_account() { return m_account; }
|
||||
|
|
@ -613,7 +589,8 @@ namespace tools
|
|||
static bool scan_pos(mining_context& cxt, std::atomic<bool>& stop, idle_condition_cb_t idle_condition_cb, const currency::core_runtime_config &runtime_config);
|
||||
bool fill_mining_context(mining_context& ctx);
|
||||
void get_transfers(wallet2::transfer_container& incoming_transfers) const;
|
||||
|
||||
std::string get_transfers_str(bool include_spent /*= true*/, bool include_unspent /*= true*/) const;
|
||||
|
||||
// Returns all payments by given id in unspecified order
|
||||
void get_payments(const std::string& payment_id, std::list<payment_details>& payments, uint64_t min_height = 0) const;
|
||||
|
||||
|
|
@ -634,6 +611,7 @@ namespace tools
|
|||
a & m_transfers;
|
||||
a & m_multisig_transfers;
|
||||
a & m_key_images;
|
||||
a & m_pending_key_images;
|
||||
a & m_unconfirmed_txs;
|
||||
a & m_unconfirmed_multisig_transfers;
|
||||
a & m_tx_keys;
|
||||
|
|
@ -813,9 +791,10 @@ private:
|
|||
const std::vector<currency::tx_destination_entry>& destinations,
|
||||
const std::vector<uint64_t>& selected_indicies);
|
||||
void mark_transfers_as_spent(const std::vector<uint64_t>& selected_transfers, const std::string& reason = std::string());
|
||||
void mark_transfers_with_flag(const std::vector<uint64_t>& selected_transfers, uint32_t flag, const std::string& reason = std::string());
|
||||
void mark_transfers_with_flag(const std::vector<uint64_t>& selected_transfers, uint32_t flag, const std::string& reason = std::string(), bool throw_if_flag_already_set = false);
|
||||
void clear_transfers_from_flag(const std::vector<uint64_t>& selected_transfers, uint32_t flag, const std::string& reason = std::string());
|
||||
void exception_handler();
|
||||
void exception_handler() const;
|
||||
uint64_t get_minimum_allowed_fee_for_contract(const crypto::hash& ms_id);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -33,22 +33,26 @@ namespace tools
|
|||
wallet_rpc_server::wallet_rpc_server(wallet2& w):m_wallet(w), m_do_mint(false)
|
||||
{}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::run(bool do_mint)
|
||||
bool wallet_rpc_server::run(bool do_mint, bool offline_mode)
|
||||
{
|
||||
m_do_mint = do_mint;
|
||||
m_net_server.add_idle_handler([this](){
|
||||
size_t blocks_fetched = 0;
|
||||
bool received_money = false;
|
||||
bool ok;
|
||||
std::atomic<bool> stop(false);
|
||||
m_wallet.refresh(blocks_fetched, received_money, ok, stop);
|
||||
if (stop)
|
||||
return true;
|
||||
|
||||
if(m_do_mint)
|
||||
m_wallet.try_mint_pos();
|
||||
return true;
|
||||
}, 2000);
|
||||
if (!offline_mode)
|
||||
{
|
||||
m_net_server.add_idle_handler([this]() {
|
||||
size_t blocks_fetched = 0;
|
||||
bool received_money = false;
|
||||
bool ok;
|
||||
std::atomic<bool> stop(false);
|
||||
m_wallet.refresh(blocks_fetched, received_money, ok, stop);
|
||||
if (stop)
|
||||
return true;
|
||||
|
||||
if (m_do_mint)
|
||||
m_wallet.try_mint_pos();
|
||||
return true;
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
//DO NOT START THIS SERVER IN MORE THEN 1 THREADS WITHOUT REFACTORING
|
||||
return epee::http_server_impl_base<wallet_rpc_server, connection_context>::run(1, true);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace tools
|
|||
|
||||
static void init_options(boost::program_options::options_description& desc);
|
||||
bool init(const boost::program_options::variables_map& vm);
|
||||
bool run(bool do_mint);
|
||||
bool run(bool do_mint, bool offline_mode);
|
||||
|
||||
CHAIN_HTTP_TO_MAP2(connection_context); //forward http requests to uri map
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue