mirror of
https://github.com/monero-project/monero.git
synced 2024-12-13 20:06:32 +02:00
wallet: include a suggested number of confirmations based on amount
This is based on how much an attacking miner stands to lose in block rewardy by mining a private chain which double spends a payment. This is not foolproof, since mining is based on luck, and breaks down as the attacking miner nears 50% of the network hash rate, and the estimation is based on a constant block reward.
This commit is contained in:
parent
a844844cda
commit
dcbc17e97e
@ -7408,8 +7408,12 @@ bool simple_wallet::show_transfer(const std::vector<std::string> &args)
|
|||||||
if (pd.m_unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
|
if (pd.m_unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
|
||||||
{
|
{
|
||||||
uint64_t bh = std::max(pd.m_unlock_time, pd.m_block_height + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE);
|
uint64_t bh = std::max(pd.m_unlock_time, pd.m_block_height + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE);
|
||||||
|
uint64_t last_block_reward = m_wallet->get_last_block_reward();
|
||||||
|
uint64_t suggested_threshold = last_block_reward ? (pd.m_amount + last_block_reward - 1) / last_block_reward : 0;
|
||||||
if (bh >= last_block_height)
|
if (bh >= last_block_height)
|
||||||
success_msg_writer() << "Locked: " << (bh - last_block_height) << " blocks to unlock";
|
success_msg_writer() << "Locked: " << (bh - last_block_height) << " blocks to unlock";
|
||||||
|
else if (suggested_threshold > 0)
|
||||||
|
success_msg_writer() << std::to_string(last_block_height - bh) << " confirmations (" << suggested_threshold << " suggested threshold)";
|
||||||
else
|
else
|
||||||
success_msg_writer() << std::to_string(last_block_height - bh) << " confirmations";
|
success_msg_writer() << std::to_string(last_block_height - bh) << " confirmations";
|
||||||
}
|
}
|
||||||
|
@ -686,7 +686,8 @@ wallet2::wallet2(network_type nettype, bool restricted):
|
|||||||
m_light_wallet_unlocked_balance(0),
|
m_light_wallet_unlocked_balance(0),
|
||||||
m_key_on_device(false),
|
m_key_on_device(false),
|
||||||
m_ring_history_saved(false),
|
m_ring_history_saved(false),
|
||||||
m_ringdb()
|
m_ringdb(),
|
||||||
|
m_last_block_reward(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1672,6 +1673,7 @@ void wallet2::process_new_blockchain_entry(const cryptonote::block& b, const cry
|
|||||||
process_new_transaction(b.tx_hashes[idx], parsed_block.txes[idx], parsed_block.o_indices.indices[idx+1].indices, height, b.timestamp, false, false, false, tx_cache_data[tx_cache_data_offset++]);
|
process_new_transaction(b.tx_hashes[idx], parsed_block.txes[idx], parsed_block.o_indices.indices[idx+1].indices, height, b.timestamp, false, false, false, tx_cache_data[tx_cache_data_offset++]);
|
||||||
}
|
}
|
||||||
TIME_MEASURE_FINISH(txs_handle_time);
|
TIME_MEASURE_FINISH(txs_handle_time);
|
||||||
|
m_last_block_reward = cryptonote::get_outs_money_amount(b.miner_tx);
|
||||||
LOG_PRINT_L2("Processed block: " << bl_id << ", height " << height << ", " << miner_tx_handle_time + txs_handle_time << "(" << miner_tx_handle_time << "/" << txs_handle_time <<")ms");
|
LOG_PRINT_L2("Processed block: " << bl_id << ", height " << height << ", " << miner_tx_handle_time + txs_handle_time << "(" << miner_tx_handle_time << "/" << txs_handle_time <<")ms");
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
@ -3166,6 +3168,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
|
|||||||
cryptonote::block b;
|
cryptonote::block b;
|
||||||
generate_genesis(b);
|
generate_genesis(b);
|
||||||
m_blockchain.push_back(get_block_hash(b));
|
m_blockchain.push_back(get_block_hash(b));
|
||||||
|
m_last_block_reward = cryptonote::get_outs_money_amount(b.miner_tx);
|
||||||
add_subaddress_account(tr("Primary account"));
|
add_subaddress_account(tr("Primary account"));
|
||||||
|
|
||||||
if (!wallet_.empty())
|
if (!wallet_.empty())
|
||||||
@ -3224,6 +3227,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
|
|||||||
cryptonote::block b;
|
cryptonote::block b;
|
||||||
generate_genesis(b);
|
generate_genesis(b);
|
||||||
m_blockchain.push_back(get_block_hash(b));
|
m_blockchain.push_back(get_block_hash(b));
|
||||||
|
m_last_block_reward = cryptonote::get_outs_money_amount(b.miner_tx);
|
||||||
add_subaddress_account(tr("Primary account"));
|
add_subaddress_account(tr("Primary account"));
|
||||||
|
|
||||||
if (!wallet_.empty())
|
if (!wallet_.empty())
|
||||||
@ -3319,6 +3323,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
|
|||||||
cryptonote::block b;
|
cryptonote::block b;
|
||||||
generate_genesis(b);
|
generate_genesis(b);
|
||||||
m_blockchain.push_back(get_block_hash(b));
|
m_blockchain.push_back(get_block_hash(b));
|
||||||
|
m_last_block_reward = cryptonote::get_outs_money_amount(b.miner_tx);
|
||||||
add_subaddress_account(tr("Primary account"));
|
add_subaddress_account(tr("Primary account"));
|
||||||
|
|
||||||
if (!wallet_.empty())
|
if (!wallet_.empty())
|
||||||
@ -3371,6 +3376,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
|
|||||||
cryptonote::block b;
|
cryptonote::block b;
|
||||||
generate_genesis(b);
|
generate_genesis(b);
|
||||||
m_blockchain.push_back(get_block_hash(b));
|
m_blockchain.push_back(get_block_hash(b));
|
||||||
|
m_last_block_reward = cryptonote::get_outs_money_amount(b.miner_tx);
|
||||||
add_subaddress_account(tr("Primary account"));
|
add_subaddress_account(tr("Primary account"));
|
||||||
|
|
||||||
if (!wallet_.empty())
|
if (!wallet_.empty())
|
||||||
@ -3417,6 +3423,7 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p
|
|||||||
m_subaddress_lookahead_major = 5;
|
m_subaddress_lookahead_major = 5;
|
||||||
m_subaddress_lookahead_minor = 20;
|
m_subaddress_lookahead_minor = 20;
|
||||||
}
|
}
|
||||||
|
m_last_block_reward = cryptonote::get_outs_money_amount(b.miner_tx);
|
||||||
add_subaddress_account(tr("Primary account"));
|
add_subaddress_account(tr("Primary account"));
|
||||||
if (!wallet_.empty()) {
|
if (!wallet_.empty()) {
|
||||||
store();
|
store();
|
||||||
@ -3513,6 +3520,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
|
|||||||
cryptonote::block b;
|
cryptonote::block b;
|
||||||
generate_genesis(b);
|
generate_genesis(b);
|
||||||
m_blockchain.push_back(get_block_hash(b));
|
m_blockchain.push_back(get_block_hash(b));
|
||||||
|
m_last_block_reward = cryptonote::get_outs_money_amount(b.miner_tx);
|
||||||
add_subaddress_account(tr("Primary account"));
|
add_subaddress_account(tr("Primary account"));
|
||||||
|
|
||||||
if (!m_wallet_file.empty())
|
if (!m_wallet_file.empty())
|
||||||
@ -4015,6 +4023,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
|
|||||||
if (m_blockchain.empty())
|
if (m_blockchain.empty())
|
||||||
{
|
{
|
||||||
m_blockchain.push_back(genesis_hash);
|
m_blockchain.push_back(genesis_hash);
|
||||||
|
m_last_block_reward = cryptonote::get_outs_money_amount(genesis.miner_tx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -4404,6 +4413,7 @@ void wallet2::rescan_blockchain(bool refresh)
|
|||||||
generate_genesis(genesis);
|
generate_genesis(genesis);
|
||||||
crypto::hash genesis_hash = get_block_hash(genesis);
|
crypto::hash genesis_hash = get_block_hash(genesis);
|
||||||
m_blockchain.push_back(genesis_hash);
|
m_blockchain.push_back(genesis_hash);
|
||||||
|
m_last_block_reward = cryptonote::get_outs_money_amount(genesis.miner_tx);
|
||||||
add_subaddress_account(tr("Primary account"));
|
add_subaddress_account(tr("Primary account"));
|
||||||
|
|
||||||
if (refresh)
|
if (refresh)
|
||||||
@ -10006,6 +10016,7 @@ void wallet2::import_blockchain(const std::tuple<size_t, crypto::hash, std::vect
|
|||||||
generate_genesis(genesis);
|
generate_genesis(genesis);
|
||||||
crypto::hash genesis_hash = get_block_hash(genesis);
|
crypto::hash genesis_hash = get_block_hash(genesis);
|
||||||
check_genesis(genesis_hash);
|
check_genesis(genesis_hash);
|
||||||
|
m_last_block_reward = cryptonote::get_outs_money_amount(genesis.miner_tx);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
std::vector<tools::wallet2::transfer_details> wallet2::export_outputs() const
|
std::vector<tools::wallet2::transfer_details> wallet2::export_outputs() const
|
||||||
|
@ -762,6 +762,9 @@ namespace tools
|
|||||||
void rescan_blockchain(bool refresh = true);
|
void rescan_blockchain(bool refresh = true);
|
||||||
bool is_transfer_unlocked(const transfer_details& td) const;
|
bool is_transfer_unlocked(const transfer_details& td) const;
|
||||||
bool is_transfer_unlocked(uint64_t unlock_time, uint64_t block_height) const;
|
bool is_transfer_unlocked(uint64_t unlock_time, uint64_t block_height) const;
|
||||||
|
|
||||||
|
uint64_t get_last_block_reward() const { return m_last_block_reward; }
|
||||||
|
|
||||||
template <class t_archive>
|
template <class t_archive>
|
||||||
inline void serialize(t_archive &a, const unsigned int ver)
|
inline void serialize(t_archive &a, const unsigned int ver)
|
||||||
{
|
{
|
||||||
@ -863,6 +866,9 @@ namespace tools
|
|||||||
if(ver < 24)
|
if(ver < 24)
|
||||||
return;
|
return;
|
||||||
a & m_ring_history_saved;
|
a & m_ring_history_saved;
|
||||||
|
if(ver < 25)
|
||||||
|
return;
|
||||||
|
a & m_last_block_reward;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1298,9 +1304,11 @@ namespace tools
|
|||||||
bool m_ring_history_saved;
|
bool m_ring_history_saved;
|
||||||
std::unique_ptr<ringdb> m_ringdb;
|
std::unique_ptr<ringdb> m_ringdb;
|
||||||
boost::optional<crypto::chacha_key> m_ringdb_key;
|
boost::optional<crypto::chacha_key> m_ringdb_key;
|
||||||
|
|
||||||
|
uint64_t m_last_block_reward;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
BOOST_CLASS_VERSION(tools::wallet2, 24)
|
BOOST_CLASS_VERSION(tools::wallet2, 25)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 9)
|
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 9)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1)
|
BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0)
|
BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0)
|
||||||
|
@ -74,6 +74,21 @@ namespace
|
|||||||
}
|
}
|
||||||
return pwd_container;
|
return pwd_container;
|
||||||
}
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
void set_confirmations(tools::wallet_rpc::transfer_entry &entry, uint64_t blockchain_height, uint64_t block_reward)
|
||||||
|
{
|
||||||
|
if (entry.height >= blockchain_height)
|
||||||
|
{
|
||||||
|
entry.confirmations = 0;
|
||||||
|
entry.suggested_confirmations_threshold = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry.confirmations = blockchain_height - entry.height;
|
||||||
|
if (block_reward == 0)
|
||||||
|
entry.suggested_confirmations_threshold = 0;
|
||||||
|
else
|
||||||
|
entry.suggested_confirmations_threshold = (entry.amount + block_reward - 1) / block_reward;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace tools
|
namespace tools
|
||||||
@ -258,6 +273,7 @@ namespace tools
|
|||||||
entry.type = "in";
|
entry.type = "in";
|
||||||
entry.subaddr_index = pd.m_subaddr_index;
|
entry.subaddr_index = pd.m_subaddr_index;
|
||||||
entry.address = m_wallet->get_subaddress_as_str(pd.m_subaddr_index);
|
entry.address = m_wallet->get_subaddress_as_str(pd.m_subaddr_index);
|
||||||
|
set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward());
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::confirmed_transfer_details &pd)
|
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::confirmed_transfer_details &pd)
|
||||||
@ -284,6 +300,7 @@ namespace tools
|
|||||||
entry.type = "out";
|
entry.type = "out";
|
||||||
entry.subaddr_index = { pd.m_subaddr_account, 0 };
|
entry.subaddr_index = { pd.m_subaddr_account, 0 };
|
||||||
entry.address = m_wallet->get_subaddress_as_str({pd.m_subaddr_account, 0});
|
entry.address = m_wallet->get_subaddress_as_str({pd.m_subaddr_account, 0});
|
||||||
|
set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward());
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::unconfirmed_transfer_details &pd)
|
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::unconfirmed_transfer_details &pd)
|
||||||
@ -303,6 +320,7 @@ namespace tools
|
|||||||
entry.type = is_failed ? "failed" : "pending";
|
entry.type = is_failed ? "failed" : "pending";
|
||||||
entry.subaddr_index = { pd.m_subaddr_account, 0 };
|
entry.subaddr_index = { pd.m_subaddr_account, 0 };
|
||||||
entry.address = m_wallet->get_subaddress_as_str({pd.m_subaddr_account, 0});
|
entry.address = m_wallet->get_subaddress_as_str({pd.m_subaddr_account, 0});
|
||||||
|
set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward());
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &payment_id, const tools::wallet2::pool_payment_details &ppd)
|
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &payment_id, const tools::wallet2::pool_payment_details &ppd)
|
||||||
@ -322,6 +340,7 @@ namespace tools
|
|||||||
entry.type = "pool";
|
entry.type = "pool";
|
||||||
entry.subaddr_index = pd.m_subaddr_index;
|
entry.subaddr_index = pd.m_subaddr_index;
|
||||||
entry.address = m_wallet->get_subaddress_as_str(pd.m_subaddr_index);
|
entry.address = m_wallet->get_subaddress_as_str(pd.m_subaddr_index);
|
||||||
|
set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward());
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool wallet_rpc_server::on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE::request& req, wallet_rpc::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er)
|
bool wallet_rpc_server::on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE::request& req, wallet_rpc::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er)
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
// advance which version they will stop working with
|
// advance which version they will stop working with
|
||||||
// Don't go over 32767 for any of these
|
// Don't go over 32767 for any of these
|
||||||
#define WALLET_RPC_VERSION_MAJOR 1
|
#define WALLET_RPC_VERSION_MAJOR 1
|
||||||
#define WALLET_RPC_VERSION_MINOR 0
|
#define WALLET_RPC_VERSION_MINOR 1
|
||||||
#define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
#define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
||||||
#define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR)
|
#define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR)
|
||||||
namespace tools
|
namespace tools
|
||||||
@ -1194,6 +1194,8 @@ namespace wallet_rpc
|
|||||||
cryptonote::subaddress_index subaddr_index;
|
cryptonote::subaddress_index subaddr_index;
|
||||||
std::string address;
|
std::string address;
|
||||||
bool double_spend_seen;
|
bool double_spend_seen;
|
||||||
|
uint64_t confirmations;
|
||||||
|
uint64_t suggested_confirmation_threshold;
|
||||||
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
KV_SERIALIZE(txid);
|
KV_SERIALIZE(txid);
|
||||||
@ -1209,6 +1211,8 @@ namespace wallet_rpc
|
|||||||
KV_SERIALIZE(subaddr_index);
|
KV_SERIALIZE(subaddr_index);
|
||||||
KV_SERIALIZE(address);
|
KV_SERIALIZE(address);
|
||||||
KV_SERIALIZE(double_spend_seen)
|
KV_SERIALIZE(double_spend_seen)
|
||||||
|
KV_SERIALIZE_OPT(confirmations, 0)
|
||||||
|
KV_SERIALIZE_OPT(suggested_confirmation_threshold, 0)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user