wallet: more user friendly print_ring
It can now take a txid (to display rings for all its inputs), and will print rings in a format that set_ring understands
This commit is contained in:
parent
798535149d
commit
eac3a11ed3
|
@ -1297,9 +1297,10 @@ bool simple_wallet::export_raw_multisig(const std::vector<std::string> &args)
|
||||||
bool simple_wallet::print_ring(const std::vector<std::string> &args)
|
bool simple_wallet::print_ring(const std::vector<std::string> &args)
|
||||||
{
|
{
|
||||||
crypto::key_image key_image;
|
crypto::key_image key_image;
|
||||||
|
crypto::hash txid;
|
||||||
if (args.size() != 1)
|
if (args.size() != 1)
|
||||||
{
|
{
|
||||||
fail_msg_writer() << tr("usage: print_ring <key_image>");
|
fail_msg_writer() << tr("usage: print_ring <key_image|txid>");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1308,20 +1309,32 @@ bool simple_wallet::print_ring(const std::vector<std::string> &args)
|
||||||
fail_msg_writer() << tr("Invalid key image");
|
fail_msg_writer() << tr("Invalid key image");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// this one will always work, they're all 32 byte hex
|
||||||
|
if (!epee::string_tools::hex_to_pod(args[0], txid))
|
||||||
|
{
|
||||||
|
fail_msg_writer() << tr("Invalid txid");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint64_t> ring;
|
std::vector<uint64_t> ring;
|
||||||
|
std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> rings;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (m_wallet->get_ring(key_image, ring))
|
if (m_wallet->get_ring(key_image, ring))
|
||||||
{
|
rings.push_back({key_image, ring});
|
||||||
std::stringstream str;
|
else if (!m_wallet->get_rings(txid, rings))
|
||||||
for (const auto &x: ring)
|
|
||||||
str << x << " ";
|
|
||||||
success_msg_writer() << tr("Ring size ") << std::to_string(ring.size()) << ": " << str.str() << tr(" (absolute)");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
fail_msg_writer() << tr("Key image either not spent, or spent with mixin 0");
|
fail_msg_writer() << tr("Key image either not spent, or spent with mixin 0");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &ring: rings)
|
||||||
|
{
|
||||||
|
std::stringstream str;
|
||||||
|
for (const auto &x: ring.second)
|
||||||
|
str << x<< " ";
|
||||||
|
// do NOT translate this "absolute" below, the lin can be used as input to set_ring
|
||||||
|
success_msg_writer() << epee::string_tools::pod_to_hex(ring.first) << " absolute " << str.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception &e)
|
||||||
|
@ -2239,8 +2252,8 @@ simple_wallet::simple_wallet()
|
||||||
tr("Export a signed multisig transaction to a file"));
|
tr("Export a signed multisig transaction to a file"));
|
||||||
m_cmd_binder.set_handler("print_ring",
|
m_cmd_binder.set_handler("print_ring",
|
||||||
boost::bind(&simple_wallet::print_ring, this, _1),
|
boost::bind(&simple_wallet::print_ring, this, _1),
|
||||||
tr("print_ring <key_image>"),
|
tr("print_ring <key_image> | <txid>"),
|
||||||
tr("Print the ring used to spend a given key image (if the ring size is > 1)"));
|
tr("Print the ring(s) used to spend a given key image or transaction (if the ring size is > 1)"));
|
||||||
m_cmd_binder.set_handler("set_ring",
|
m_cmd_binder.set_handler("set_ring",
|
||||||
boost::bind(&simple_wallet::set_ring, this, _1),
|
boost::bind(&simple_wallet::set_ring, this, _1),
|
||||||
tr("set_ring <key_image> absolute|relative <index> [<index>...]"),
|
tr("set_ring <key_image> absolute|relative <index> [<index>...]"),
|
||||||
|
|
|
@ -1971,6 +1971,30 @@ bool WalletImpl::getRing(const std::string &key_image, std::vector<uint64_t> &ri
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WalletImpl::getRings(const std::string &txid, std::vector<std::pair<std::string, std::vector<uint64_t>>> &rings) const
|
||||||
|
{
|
||||||
|
crypto::hash raw_txid;
|
||||||
|
if (!epee::string_tools::hex_to_pod(txid, raw_txid))
|
||||||
|
{
|
||||||
|
m_status = Status_Error;
|
||||||
|
m_errorString = tr("Failed to parse txid");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> raw_rings;
|
||||||
|
bool ret = m_wallet->get_rings(raw_txid, raw_rings);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
m_status = Status_Error;
|
||||||
|
m_errorString = tr("Failed to get rings");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (const auto &r: raw_rings)
|
||||||
|
{
|
||||||
|
rings.push_back(std::make_pair(epee::string_tools::pod_to_hex(r.first), r.second));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool WalletImpl::setRing(const std::string &key_image, const std::vector<uint64_t> &ring, bool relative)
|
bool WalletImpl::setRing(const std::string &key_image, const std::vector<uint64_t> &ring, bool relative)
|
||||||
{
|
{
|
||||||
crypto::key_image raw_key_image;
|
crypto::key_image raw_key_image;
|
||||||
|
|
|
@ -166,6 +166,7 @@ public:
|
||||||
virtual bool blackballOutputs(const std::vector<std::string> &pubkeys, bool add);
|
virtual bool blackballOutputs(const std::vector<std::string> &pubkeys, bool add);
|
||||||
virtual bool unblackballOutput(const std::string &pubkey);
|
virtual bool unblackballOutput(const std::string &pubkey);
|
||||||
virtual bool getRing(const std::string &key_image, std::vector<uint64_t> &ring) const;
|
virtual bool getRing(const std::string &key_image, std::vector<uint64_t> &ring) const;
|
||||||
|
virtual bool getRings(const std::string &txid, std::vector<std::pair<std::string, std::vector<uint64_t>>> &rings) const;
|
||||||
virtual bool setRing(const std::string &key_image, const std::vector<uint64_t> &ring, bool relative);
|
virtual bool setRing(const std::string &key_image, const std::vector<uint64_t> &ring, bool relative);
|
||||||
virtual void segregatePreForkOutputs(bool segregate);
|
virtual void segregatePreForkOutputs(bool segregate);
|
||||||
virtual void segregationHeight(uint64_t height);
|
virtual void segregationHeight(uint64_t height);
|
||||||
|
|
|
@ -766,6 +766,9 @@ struct Wallet
|
||||||
//! gets the ring used for a key image, if any
|
//! gets the ring used for a key image, if any
|
||||||
virtual bool getRing(const std::string &key_image, std::vector<uint64_t> &ring) const = 0;
|
virtual bool getRing(const std::string &key_image, std::vector<uint64_t> &ring) const = 0;
|
||||||
|
|
||||||
|
//! gets the rings used for a txid, if any
|
||||||
|
virtual bool getRings(const std::string &txid, std::vector<std::pair<std::string, std::vector<uint64_t>>> &rings) const = 0;
|
||||||
|
|
||||||
//! sets the ring used for a key image
|
//! sets the ring used for a key image
|
||||||
virtual bool setRing(const std::string &key_image, const std::vector<uint64_t> &ring, bool relative) = 0;
|
virtual bool setRing(const std::string &key_image, const std::vector<uint64_t> &ring, bool relative) = 0;
|
||||||
|
|
||||||
|
|
|
@ -1521,6 +1521,14 @@ void wallet2::process_outgoing(const crypto::hash &txid, const cryptonote::trans
|
||||||
entry.first->second.m_subaddr_account = subaddr_account;
|
entry.first->second.m_subaddr_account = subaddr_account;
|
||||||
entry.first->second.m_subaddr_indices = subaddr_indices;
|
entry.first->second.m_subaddr_indices = subaddr_indices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto &in: tx.vin)
|
||||||
|
{
|
||||||
|
if (in.type() != typeid(cryptonote::txin_to_key))
|
||||||
|
continue;
|
||||||
|
const auto &txin = boost::get<cryptonote::txin_to_key>(in);
|
||||||
|
entry.first->second.m_rings.push_back(std::make_pair(txin.k_image, txin.key_offsets));
|
||||||
|
}
|
||||||
entry.first->second.m_block_height = height;
|
entry.first->second.m_block_height = height;
|
||||||
entry.first->second.m_timestamp = ts;
|
entry.first->second.m_timestamp = ts;
|
||||||
entry.first->second.m_unlock_time = tx.unlock_time;
|
entry.first->second.m_unlock_time = tx.unlock_time;
|
||||||
|
@ -4390,6 +4398,13 @@ void wallet2::add_unconfirmed_tx(const cryptonote::transaction& tx, uint64_t amo
|
||||||
utd.m_timestamp = time(NULL);
|
utd.m_timestamp = time(NULL);
|
||||||
utd.m_subaddr_account = subaddr_account;
|
utd.m_subaddr_account = subaddr_account;
|
||||||
utd.m_subaddr_indices = subaddr_indices;
|
utd.m_subaddr_indices = subaddr_indices;
|
||||||
|
for (const auto &in: tx.vin)
|
||||||
|
{
|
||||||
|
if (in.type() != typeid(cryptonote::txin_to_key))
|
||||||
|
continue;
|
||||||
|
const auto &txin = boost::get<cryptonote::txin_to_key>(in);
|
||||||
|
utd.m_rings.push_back(std::make_pair(txin.k_image, txin.key_offsets));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
@ -4545,8 +4560,6 @@ void wallet2::commit_tx(pending_tx& ptx)
|
||||||
m_additional_tx_keys.insert(std::make_pair(txid, ptx.additional_tx_keys));
|
m_additional_tx_keys.insert(std::make_pair(txid, ptx.additional_tx_keys));
|
||||||
}
|
}
|
||||||
|
|
||||||
add_rings(ptx.tx);
|
|
||||||
|
|
||||||
LOG_PRINT_L2("transaction " << txid << " generated ok and sent to daemon, key_images: [" << ptx.key_images << "]");
|
LOG_PRINT_L2("transaction " << txid << " generated ok and sent to daemon, key_images: [" << ptx.key_images << "]");
|
||||||
|
|
||||||
for(size_t idx: ptx.selected_transfers)
|
for(size_t idx: ptx.selected_transfers)
|
||||||
|
@ -5490,6 +5503,29 @@ bool wallet2::get_ring(const crypto::chacha_key &key, const crypto::key_image &k
|
||||||
return m_ringdb->get_ring(key, key_image, outs);
|
return m_ringdb->get_ring(key, key_image, outs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wallet2::get_rings(const crypto::hash &txid, std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> &outs)
|
||||||
|
{
|
||||||
|
for (auto i: m_confirmed_txs)
|
||||||
|
{
|
||||||
|
if (txid == i.first)
|
||||||
|
{
|
||||||
|
for (const auto &x: i.second.m_rings)
|
||||||
|
outs.push_back({x.first, cryptonote::relative_output_offsets_to_absolute(x.second)});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto i: m_unconfirmed_txs)
|
||||||
|
{
|
||||||
|
if (txid == i.first)
|
||||||
|
{
|
||||||
|
for (const auto &x: i.second.m_rings)
|
||||||
|
outs.push_back({x.first, cryptonote::relative_output_offsets_to_absolute(x.second)});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool wallet2::get_ring(const crypto::key_image &key_image, std::vector<uint64_t> &outs)
|
bool wallet2::get_ring(const crypto::key_image &key_image, std::vector<uint64_t> &outs)
|
||||||
{
|
{
|
||||||
crypto::chacha_key key;
|
crypto::chacha_key key;
|
||||||
|
|
|
@ -289,6 +289,7 @@ namespace tools
|
||||||
uint64_t m_timestamp;
|
uint64_t m_timestamp;
|
||||||
uint32_t m_subaddr_account; // subaddress account of your wallet to be used in this transfer
|
uint32_t m_subaddr_account; // subaddress account of your wallet to be used in this transfer
|
||||||
std::set<uint32_t> m_subaddr_indices; // set of address indices used as inputs in this transfer
|
std::set<uint32_t> m_subaddr_indices; // set of address indices used as inputs in this transfer
|
||||||
|
std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> m_rings; // relative
|
||||||
};
|
};
|
||||||
|
|
||||||
struct confirmed_transfer_details
|
struct confirmed_transfer_details
|
||||||
|
@ -303,10 +304,11 @@ namespace tools
|
||||||
uint64_t m_unlock_time;
|
uint64_t m_unlock_time;
|
||||||
uint32_t m_subaddr_account; // subaddress account of your wallet to be used in this transfer
|
uint32_t m_subaddr_account; // subaddress account of your wallet to be used in this transfer
|
||||||
std::set<uint32_t> m_subaddr_indices; // set of address indices used as inputs in this transfer
|
std::set<uint32_t> m_subaddr_indices; // set of address indices used as inputs in this transfer
|
||||||
|
std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> m_rings; // relative
|
||||||
|
|
||||||
confirmed_transfer_details(): m_amount_in(0), m_amount_out(0), m_change((uint64_t)-1), m_block_height(0), m_payment_id(crypto::null_hash), m_timestamp(0), m_unlock_time(0), m_subaddr_account((uint32_t)-1) {}
|
confirmed_transfer_details(): m_amount_in(0), m_amount_out(0), m_change((uint64_t)-1), m_block_height(0), m_payment_id(crypto::null_hash), m_timestamp(0), m_unlock_time(0), m_subaddr_account((uint32_t)-1) {}
|
||||||
confirmed_transfer_details(const unconfirmed_transfer_details &utd, uint64_t height):
|
confirmed_transfer_details(const unconfirmed_transfer_details &utd, uint64_t height):
|
||||||
m_amount_in(utd.m_amount_in), m_amount_out(utd.m_amount_out), m_change(utd.m_change), m_block_height(height), m_dests(utd.m_dests), m_payment_id(utd.m_payment_id), m_timestamp(utd.m_timestamp), m_unlock_time(utd.m_tx.unlock_time), m_subaddr_account(utd.m_subaddr_account), m_subaddr_indices(utd.m_subaddr_indices) {}
|
m_amount_in(utd.m_amount_in), m_amount_out(utd.m_amount_out), m_change(utd.m_change), m_block_height(height), m_dests(utd.m_dests), m_payment_id(utd.m_payment_id), m_timestamp(utd.m_timestamp), m_unlock_time(utd.m_tx.unlock_time), m_subaddr_account(utd.m_subaddr_account), m_subaddr_indices(utd.m_subaddr_indices), m_rings(utd.m_rings) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tx_construction_data
|
struct tx_construction_data
|
||||||
|
@ -1059,6 +1061,7 @@ namespace tools
|
||||||
void set_ring_database(const std::string &filename);
|
void set_ring_database(const std::string &filename);
|
||||||
const std::string get_ring_database() const { return m_ring_database; }
|
const std::string get_ring_database() const { return m_ring_database; }
|
||||||
bool get_ring(const crypto::key_image &key_image, std::vector<uint64_t> &outs);
|
bool get_ring(const crypto::key_image &key_image, std::vector<uint64_t> &outs);
|
||||||
|
bool get_rings(const crypto::hash &txid, std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> &outs);
|
||||||
bool set_ring(const crypto::key_image &key_image, const std::vector<uint64_t> &outs, bool relative);
|
bool set_ring(const crypto::key_image &key_image, const std::vector<uint64_t> &outs, bool relative);
|
||||||
bool find_and_save_rings(bool force = true);
|
bool find_and_save_rings(bool force = true);
|
||||||
|
|
||||||
|
@ -1227,8 +1230,8 @@ BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::multisig_tx_set, 1)
|
BOOST_CLASS_VERSION(tools::wallet2::multisig_tx_set, 1)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::payment_details, 3)
|
BOOST_CLASS_VERSION(tools::wallet2::payment_details, 3)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::pool_payment_details, 1)
|
BOOST_CLASS_VERSION(tools::wallet2::pool_payment_details, 1)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 7)
|
BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 8)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 5)
|
BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 6)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::address_book_row, 17)
|
BOOST_CLASS_VERSION(tools::wallet2::address_book_row, 17)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::reserve_proof_entry, 0)
|
BOOST_CLASS_VERSION(tools::wallet2::reserve_proof_entry, 0)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::unsigned_tx_set, 0)
|
BOOST_CLASS_VERSION(tools::wallet2::unsigned_tx_set, 0)
|
||||||
|
@ -1428,6 +1431,9 @@ namespace boost
|
||||||
}
|
}
|
||||||
a & x.m_subaddr_account;
|
a & x.m_subaddr_account;
|
||||||
a & x.m_subaddr_indices;
|
a & x.m_subaddr_indices;
|
||||||
|
if (ver < 8)
|
||||||
|
return;
|
||||||
|
a & x.m_rings;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
|
@ -1472,6 +1478,9 @@ namespace boost
|
||||||
}
|
}
|
||||||
a & x.m_subaddr_account;
|
a & x.m_subaddr_account;
|
||||||
a & x.m_subaddr_indices;
|
a & x.m_subaddr_indices;
|
||||||
|
if (ver < 6)
|
||||||
|
return;
|
||||||
|
a & x.m_rings;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
|
|
Loading…
Reference in New Issue