forked from lthn/blockchain
auditable watch-only wallet now can be restored from awo-blob (by a third party): --restore-awo-wallet
simplewallet new command: awo_blob
This commit is contained in:
parent
069cbbf769
commit
ee9ef363b9
8 changed files with 125 additions and 10 deletions
|
|
@ -162,6 +162,13 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
bool account_base::restore_from_awo_blob(const std::string& awo_blob)
|
||||
{
|
||||
set_null();
|
||||
bool r = parse_awo_blob(awo_blob, m_keys.account_address, m_keys.view_secret_key, m_creation_timestamp);
|
||||
return r;
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
std::string account_base::get_public_address_str() const
|
||||
{
|
||||
//TODO: change this code into base 58
|
||||
|
|
@ -172,7 +179,7 @@ namespace currency
|
|||
{
|
||||
// keep only:
|
||||
// timestamp
|
||||
// view pub & spend pub (public address)
|
||||
// view pub & spend pub + flags (public address)
|
||||
// view sec
|
||||
|
||||
// store to local tmp
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ namespace currency
|
|||
|
||||
std::string get_restore_braindata() const;
|
||||
bool restore_from_braindata(const std::string& seed_phrase);
|
||||
bool restore_from_awo_blob(const std::string& awo_blob);
|
||||
|
||||
uint64_t get_createtime() const { return m_creation_timestamp; }
|
||||
void set_createtime(uint64_t val) { m_creation_timestamp = val; }
|
||||
|
|
|
|||
|
|
@ -313,6 +313,46 @@ namespace currency
|
|||
return string_tools::get_xtype_from_string(amount, str_amount);
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
bool parse_awo_blob(const std::string& awo_blob, account_public_address& address, crypto::secret_key& view_sec_key, uint64_t& creation_timestamp)
|
||||
{
|
||||
std::vector<std::string> parts;
|
||||
boost::split(parts, awo_blob, [](char x){ return x == ':'; } );
|
||||
if (parts.size() != 2 && parts.size() != 3)
|
||||
return false;
|
||||
|
||||
if (!get_account_address_from_str(address, parts[0]))
|
||||
return false;
|
||||
|
||||
if (!address.is_auditable())
|
||||
return false;
|
||||
|
||||
if (!epee::string_tools::parse_tpod_from_hex_string(parts[1], view_sec_key))
|
||||
return false;
|
||||
|
||||
crypto::public_key view_pub_key = AUTO_VAL_INIT(view_pub_key);
|
||||
if (!crypto::secret_key_to_public_key(view_sec_key, view_pub_key))
|
||||
return false;
|
||||
|
||||
if (view_pub_key != address.view_public_key)
|
||||
return false;
|
||||
|
||||
creation_timestamp = 0;
|
||||
if (parts.size() == 3)
|
||||
{
|
||||
// parse timestamp
|
||||
int64_t ts = 0;
|
||||
if (!epee::string_tools::string_to_num_fast(parts[2], ts))
|
||||
return false;
|
||||
|
||||
if (ts < WALLET_BRAIN_DATE_OFFSET)
|
||||
return false;
|
||||
|
||||
creation_timestamp = ts;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
std::string print_stake_kernel_info(const stake_kernel& sk)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
|
|
|||
|
|
@ -239,6 +239,7 @@ namespace currency
|
|||
bool check_inputs_types_supported(const transaction& tx);
|
||||
bool check_outs_valid(const transaction& tx);
|
||||
bool parse_amount(uint64_t& amount, const std::string& str_amount);
|
||||
bool parse_awo_blob(const std::string& awo_blob, account_public_address& address, crypto::secret_key& view_sec_key, uint64_t& creation_timestamp);
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ namespace
|
|||
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_pos_mining_reward_address = { "pos-mining-reward-address", "Block reward will be sent to the giving address if specified", "" };
|
||||
const command_line::arg_descriptor<std::string> arg_restore_wallet = { "restore-wallet", "Restore wallet from the seed phrase and save it to <arg>", "" };
|
||||
const command_line::arg_descriptor<std::string> arg_restore_awo_wallet = { "restore-awo-wallet", "Restore auditable watch-only wallet from address and view key. Use \"address:viewkey\" as argument", "" };
|
||||
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", ""};
|
||||
|
|
@ -220,6 +221,8 @@ simple_wallet::simple_wallet()
|
|||
|
||||
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("awo_blob", boost::bind(&simple_wallet::awo_blob, this, _1), "For auditable wallets: prints auditable watch-only blob for wallet's audit by a third party");
|
||||
|
||||
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.");
|
||||
|
||||
|
|
@ -271,9 +274,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (m_wallet_file.empty() && m_generate_new.empty() && m_restore_wallet.empty() && m_generate_new_aw.empty())
|
||||
if (m_wallet_file.empty() && m_generate_new.empty() && m_restore_wallet.empty() && m_restore_awo_wallet.empty() && m_generate_new_aw.empty())
|
||||
{
|
||||
fail_msg_writer() << "you must specify --wallet-file, --generate-new-wallet, --generate-new-auditable-wallet or --restore-wallet";
|
||||
fail_msg_writer() << "you must specify --wallet-file, --generate-new-wallet, --generate-new-auditable-wallet, --restore-wallet or --restore-awo-wallet";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -335,7 +338,25 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool r = restore_wallet(m_restore_wallet, restore_seed_container.password(), pwd_container.password());
|
||||
bool r = restore_wallet(m_restore_wallet, restore_seed_container.password(), pwd_container.password(), false);
|
||||
CHECK_AND_ASSERT_MES(r, false, "wallet restoring failed");
|
||||
}
|
||||
else if (!m_restore_awo_wallet.empty())
|
||||
{
|
||||
if (boost::filesystem::exists(m_restore_awo_wallet))
|
||||
{
|
||||
fail_msg_writer() << "file " << m_restore_awo_wallet << " already exists";
|
||||
return false;
|
||||
}
|
||||
|
||||
tools::password_container restore_addr_and_viewkey_container;
|
||||
if (!restore_addr_and_viewkey_container.read_password("please, enter wallet auditable address, viewkey and timestamp, separated by a colon (\"address:viewkey:timestamp\"):\n"))
|
||||
{
|
||||
fail_msg_writer() << "failed to read seed phrase";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool r = restore_wallet(m_restore_awo_wallet, restore_addr_and_viewkey_container.password(), pwd_container.password(), true);
|
||||
CHECK_AND_ASSERT_MES(r, false, "wallet restoring failed");
|
||||
}
|
||||
else
|
||||
|
|
@ -366,6 +387,7 @@ void simple_wallet::handle_command_line(const boost::program_options::variables_
|
|||
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);
|
||||
m_restore_awo_wallet = command_line::get_arg(vm, arg_restore_awo_wallet);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::try_connect_to_daemon()
|
||||
|
|
@ -417,7 +439,7 @@ 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)
|
||||
bool simple_wallet::restore_wallet(const std::string &wallet_file, const std::string &seed_or_awo_blob, const std::string& password, bool auditable_watch_only)
|
||||
{
|
||||
m_wallet_file = wallet_file;
|
||||
|
||||
|
|
@ -426,15 +448,24 @@ bool simple_wallet::restore_wallet(const std::string &wallet_file, const std::st
|
|||
m_wallet->set_do_rise_transfer(false);
|
||||
try
|
||||
{
|
||||
m_wallet->restore(epee::string_encoding::utf8_to_wstring(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().view_secret_key) << std::endl << std::flush;
|
||||
if (auditable_watch_only)
|
||||
{
|
||||
m_wallet->restore_awo(epee::string_encoding::utf8_to_wstring(wallet_file), password, seed_or_awo_blob);
|
||||
message_writer(epee::log_space::console_color_white, true) << "Auditable watch-only wallet restored: " << m_wallet->get_account().get_public_address_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal wallet
|
||||
m_wallet->restore(epee::string_encoding::utf8_to_wstring(wallet_file), password, seed_or_awo_blob);
|
||||
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().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, check your seed phrase!" << ENDL << e.what();
|
||||
fail_msg_writer() << "failed to restore wallet, check your " << (auditable_watch_only ? "awo blob!" : "seed phrase!") << ENDL << e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1471,6 +1502,24 @@ bool simple_wallet::get_tx_key(const std::vector<std::string> &args_)
|
|||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::awo_blob(const std::vector<std::string> &args_)
|
||||
{
|
||||
if (!m_wallet->is_auditable())
|
||||
{
|
||||
fail_msg_writer() << "this command is allowed for auditable wallets only";
|
||||
return true;
|
||||
}
|
||||
|
||||
const account_base& acc = m_wallet->get_account();
|
||||
|
||||
success_msg_writer() << "Auditable watch-only blob for this wallet is: ";
|
||||
std::cout << acc.get_public_address_str() << ":" << epee::string_tools::pod_to_hex(acc.get_keys().view_secret_key);
|
||||
if (acc.get_createtime())
|
||||
std::cout << ":" << acc.get_createtime();
|
||||
std::cout << ENDL;
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void simple_wallet::set_offline_mode(bool offline_mode)
|
||||
{
|
||||
if (offline_mode && !m_offline_mode)
|
||||
|
|
@ -1734,6 +1783,7 @@ int main(int argc, char* argv[])
|
|||
command_line::add_arg(desc_params, arg_do_pos_mining);
|
||||
command_line::add_arg(desc_params, arg_pos_mining_reward_address);
|
||||
command_line::add_arg(desc_params, arg_restore_wallet);
|
||||
command_line::add_arg(desc_params, arg_restore_awo_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);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ namespace currency
|
|||
|
||||
bool new_wallet(const std::string &wallet_file, const std::string& password, bool create_auditable_wallet);
|
||||
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 restore_wallet(const std::string &wallet_file, const std::string &seed_or_awo_blob, const std::string& password, bool auditable_watch_only);
|
||||
bool close_wallet();
|
||||
|
||||
bool help(const std::vector<std::string> &args = std::vector<std::string>());
|
||||
|
|
@ -81,6 +81,7 @@ namespace currency
|
|||
bool enable_console_logger(const std::vector<std::string> &args);
|
||||
bool integrated_address(const std::vector<std::string> &args);
|
||||
bool get_tx_key(const std::vector<std::string> &args_);
|
||||
bool awo_blob(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);
|
||||
|
|
@ -166,6 +167,7 @@ namespace currency
|
|||
bool m_do_pos_mining;
|
||||
bool m_offline_mode;
|
||||
std::string m_restore_wallet;
|
||||
std::string m_restore_awo_wallet;
|
||||
|
||||
epee::console_handlers_binder m_cmd_binder;
|
||||
|
||||
|
|
|
|||
|
|
@ -2203,6 +2203,19 @@ void wallet2::restore(const std::wstring& path, const std::string& pass, const s
|
|||
store();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::restore_awo(const std::wstring& path, const std::string& pass, const std::string& awo_blob)
|
||||
{
|
||||
clear();
|
||||
prepare_file_names(path);
|
||||
m_password = pass;
|
||||
bool r = m_account.restore_from_awo_blob(awo_blob);
|
||||
init_log_prefix();
|
||||
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(r, "Could not load auditable watch-only wallet from a given blob: invalid awo blob");
|
||||
boost::system::error_code ignored_ec;
|
||||
THROW_IF_FALSE_WALLET_EX(!boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, epee::string_encoding::convert_to_ansii(m_wallet_file));
|
||||
store();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::check_connection()
|
||||
{
|
||||
return m_core_proxy->check_connection();
|
||||
|
|
|
|||
|
|
@ -489,6 +489,7 @@ namespace tools
|
|||
void assign_account(const currency::account_base& acc);
|
||||
void generate(const std::wstring& path, const std::string& password, bool auditable_wallet);
|
||||
void restore(const std::wstring& path, const std::string& pass, const std::string& seed_phrase);
|
||||
void restore_awo(const std::wstring& path, const std::string& pass, const std::string& awo_blob);
|
||||
void load(const std::wstring& path, const std::string& password);
|
||||
void store();
|
||||
void store(const std::wstring& path);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue