wallet: on first refresh, start off with a quantized height
for privacy reasons, so an untrusted node can't easily track wallets from IP address to IP address, etc. The granularity is 1024 blocks, which is about a day and a half.
This commit is contained in:
parent
62f3f0480a
commit
8db23df581
|
@ -3885,7 +3885,7 @@ bool simple_wallet::refresh_main(uint64_t start_height, bool reset, bool is_init
|
||||||
{
|
{
|
||||||
m_in_manual_refresh.store(true, std::memory_order_relaxed);
|
m_in_manual_refresh.store(true, std::memory_order_relaxed);
|
||||||
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){m_in_manual_refresh.store(false, std::memory_order_relaxed);});
|
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){m_in_manual_refresh.store(false, std::memory_order_relaxed);});
|
||||||
m_wallet->refresh(start_height, fetched_blocks);
|
m_wallet->refresh(is_daemon_trusted(), start_height, fetched_blocks);
|
||||||
ok = true;
|
ok = true;
|
||||||
// Clear line "Height xxx of xxx"
|
// Clear line "Height xxx of xxx"
|
||||||
std::cout << "\r \r";
|
std::cout << "\r \r";
|
||||||
|
@ -6393,7 +6393,7 @@ void simple_wallet::wallet_idle_thread()
|
||||||
{
|
{
|
||||||
uint64_t fetched_blocks;
|
uint64_t fetched_blocks;
|
||||||
if (try_connect_to_daemon(true))
|
if (try_connect_to_daemon(true))
|
||||||
m_wallet->refresh(0, fetched_blocks);
|
m_wallet->refresh(is_daemon_trusted(), 0, fetched_blocks);
|
||||||
}
|
}
|
||||||
catch(...) {}
|
catch(...) {}
|
||||||
m_auto_refresh_refreshing = false;
|
m_auto_refresh_refreshing = false;
|
||||||
|
|
|
@ -115,6 +115,8 @@ using namespace cryptonote;
|
||||||
#define STAGENET_SEGREGATION_FORK_HEIGHT 1000000
|
#define STAGENET_SEGREGATION_FORK_HEIGHT 1000000
|
||||||
#define SEGREGATION_FORK_VICINITY 1500 /* blocks */
|
#define SEGREGATION_FORK_VICINITY 1500 /* blocks */
|
||||||
|
|
||||||
|
#define FIRST_REFRESH_GRANULARITY 1024
|
||||||
|
|
||||||
static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1";
|
static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1";
|
||||||
|
|
||||||
|
|
||||||
|
@ -654,6 +656,7 @@ wallet2::wallet2(network_type nettype, bool restricted):
|
||||||
m_default_priority(0),
|
m_default_priority(0),
|
||||||
m_refresh_type(RefreshOptimizeCoinbase),
|
m_refresh_type(RefreshOptimizeCoinbase),
|
||||||
m_auto_refresh(true),
|
m_auto_refresh(true),
|
||||||
|
m_first_refresh_done(false),
|
||||||
m_refresh_from_block_height(0),
|
m_refresh_from_block_height(0),
|
||||||
m_explicit_refresh_from_block_height(true),
|
m_explicit_refresh_from_block_height(true),
|
||||||
m_confirm_missing_payment_id(true),
|
m_confirm_missing_payment_id(true),
|
||||||
|
@ -1608,11 +1611,12 @@ void wallet2::process_new_blockchain_entry(const cryptonote::block& b, const cry
|
||||||
m_callback->on_new_block(height, b);
|
m_callback->on_new_block(height, b);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::get_short_chain_history(std::list<crypto::hash>& ids) const
|
void wallet2::get_short_chain_history(std::list<crypto::hash>& ids, uint64_t granularity) const
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
size_t current_multiplier = 1;
|
size_t current_multiplier = 1;
|
||||||
size_t sz = m_blockchain.size() - m_blockchain.offset();
|
size_t blockchain_size = std::max(m_blockchain.size() / granularity * granularity, m_blockchain.offset());
|
||||||
|
size_t sz = blockchain_size - m_blockchain.offset();
|
||||||
if(!sz)
|
if(!sz)
|
||||||
{
|
{
|
||||||
ids.push_back(m_blockchain.genesis());
|
ids.push_back(m_blockchain.genesis());
|
||||||
|
@ -1818,16 +1822,16 @@ void wallet2::process_blocks(uint64_t start_height, const std::list<cryptonote::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::refresh()
|
void wallet2::refresh(bool trusted_daemon)
|
||||||
{
|
{
|
||||||
uint64_t blocks_fetched = 0;
|
uint64_t blocks_fetched = 0;
|
||||||
refresh(0, blocks_fetched);
|
refresh(trusted_daemon, 0, blocks_fetched);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched)
|
void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blocks_fetched)
|
||||||
{
|
{
|
||||||
bool received_money = false;
|
bool received_money = false;
|
||||||
refresh(start_height, blocks_fetched, received_money);
|
refresh(trusted_daemon, start_height, blocks_fetched, received_money);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::list<cryptonote::block_complete_entry> &prev_blocks, std::list<cryptonote::block_complete_entry> &blocks, std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices, bool &error)
|
void wallet2::pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::list<cryptonote::block_complete_entry> &prev_blocks, std::list<cryptonote::block_complete_entry> &blocks, std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices, bool &error)
|
||||||
|
@ -2196,7 +2200,7 @@ bool wallet2::delete_address_book_row(std::size_t row_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& received_money)
|
void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blocks_fetched, bool& received_money)
|
||||||
{
|
{
|
||||||
if(m_light_wallet) {
|
if(m_light_wallet) {
|
||||||
|
|
||||||
|
@ -2245,7 +2249,7 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re
|
||||||
bool refreshed = false;
|
bool refreshed = false;
|
||||||
|
|
||||||
// pull the first set of blocks
|
// pull the first set of blocks
|
||||||
get_short_chain_history(short_chain_history);
|
get_short_chain_history(short_chain_history, (m_first_refresh_done || trusted_daemon) ? 1 : FIRST_REFRESH_GRANULARITY);
|
||||||
m_run.store(true, std::memory_order_relaxed);
|
m_run.store(true, std::memory_order_relaxed);
|
||||||
if (start_height > m_blockchain.size() || m_refresh_from_block_height > m_blockchain.size()) {
|
if (start_height > m_blockchain.size() || m_refresh_from_block_height > m_blockchain.size()) {
|
||||||
if (!start_height)
|
if (!start_height)
|
||||||
|
@ -2254,7 +2258,7 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re
|
||||||
fast_refresh(start_height, blocks_start_height, short_chain_history);
|
fast_refresh(start_height, blocks_start_height, short_chain_history);
|
||||||
// regenerate the history now that we've got a full set of hashes
|
// regenerate the history now that we've got a full set of hashes
|
||||||
short_chain_history.clear();
|
short_chain_history.clear();
|
||||||
get_short_chain_history(short_chain_history);
|
get_short_chain_history(short_chain_history, (m_first_refresh_done || trusted_daemon) ? 1 : FIRST_REFRESH_GRANULARITY);
|
||||||
start_height = 0;
|
start_height = 0;
|
||||||
// and then fall through to regular refresh processing
|
// and then fall through to regular refresh processing
|
||||||
}
|
}
|
||||||
|
@ -2334,14 +2338,16 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re
|
||||||
LOG_PRINT_L1("Failed to check pending transactions");
|
LOG_PRINT_L1("Failed to check pending transactions");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_first_refresh_done = true;
|
||||||
|
|
||||||
LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", balance (all accounts): " << print_money(balance_all()) << ", unlocked: " << print_money(unlocked_balance_all()));
|
LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", balance (all accounts): " << print_money(balance_all()) << ", unlocked: " << print_money(unlocked_balance_all()));
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
bool wallet2::refresh(uint64_t & blocks_fetched, bool& received_money, bool& ok)
|
bool wallet2::refresh(bool trusted_daemon, uint64_t & blocks_fetched, bool& received_money, bool& ok)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
refresh(0, blocks_fetched, received_money);
|
refresh(trusted_daemon, 0, blocks_fetched, received_money);
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
|
@ -4256,7 +4262,7 @@ void wallet2::rescan_blockchain(bool refresh)
|
||||||
m_local_bc_height = 1;
|
m_local_bc_height = 1;
|
||||||
|
|
||||||
if (refresh)
|
if (refresh)
|
||||||
this->refresh();
|
this->refresh(false);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
bool wallet2::is_transfer_unlocked(const transfer_details& td) const
|
bool wallet2::is_transfer_unlocked(const transfer_details& td) const
|
||||||
|
@ -10118,7 +10124,7 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
|
||||||
m_multisig_rescan_info = &info;
|
m_multisig_rescan_info = &info;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
refresh();
|
refresh(false);
|
||||||
}
|
}
|
||||||
catch (...) {}
|
catch (...) {}
|
||||||
m_multisig_rescan_info = NULL;
|
m_multisig_rescan_info = NULL;
|
||||||
|
|
|
@ -642,10 +642,10 @@ namespace tools
|
||||||
* \brief Tells if the wallet file is deprecated.
|
* \brief Tells if the wallet file is deprecated.
|
||||||
*/
|
*/
|
||||||
bool is_deprecated() const;
|
bool is_deprecated() const;
|
||||||
void refresh();
|
void refresh(bool trusted_daemon);
|
||||||
void refresh(uint64_t start_height, uint64_t & blocks_fetched);
|
void refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blocks_fetched);
|
||||||
void refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& received_money);
|
void refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blocks_fetched, bool& received_money);
|
||||||
bool refresh(uint64_t & blocks_fetched, bool& received_money, bool& ok);
|
bool refresh(bool trusted_daemon, uint64_t & blocks_fetched, bool& received_money, bool& ok);
|
||||||
|
|
||||||
void set_refresh_type(RefreshType refresh_type) { m_refresh_type = refresh_type; }
|
void set_refresh_type(RefreshType refresh_type) { m_refresh_type = refresh_type; }
|
||||||
RefreshType get_refresh_type() const { return m_refresh_type; }
|
RefreshType get_refresh_type() const { return m_refresh_type; }
|
||||||
|
@ -1112,7 +1112,7 @@ namespace tools
|
||||||
void process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen);
|
void process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen);
|
||||||
void process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const crypto::hash& bl_id, uint64_t height, const cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices &o_indices);
|
void process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const crypto::hash& bl_id, uint64_t height, const cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices &o_indices);
|
||||||
void detach_blockchain(uint64_t height);
|
void detach_blockchain(uint64_t height);
|
||||||
void get_short_chain_history(std::list<crypto::hash>& ids) const;
|
void get_short_chain_history(std::list<crypto::hash>& ids, uint64_t granularity = 1) const;
|
||||||
bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_height) const;
|
bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_height) const;
|
||||||
bool clear();
|
bool clear();
|
||||||
void pull_blocks(uint64_t start_height, uint64_t& blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::list<cryptonote::block_complete_entry> &blocks, std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices);
|
void pull_blocks(uint64_t start_height, uint64_t& blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::list<cryptonote::block_complete_entry> &blocks, std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices);
|
||||||
|
@ -1210,6 +1210,7 @@ namespace tools
|
||||||
uint32_t m_default_priority;
|
uint32_t m_default_priority;
|
||||||
RefreshType m_refresh_type;
|
RefreshType m_refresh_type;
|
||||||
bool m_auto_refresh;
|
bool m_auto_refresh;
|
||||||
|
bool m_first_refresh_done;
|
||||||
uint64_t m_refresh_from_block_height;
|
uint64_t m_refresh_from_block_height;
|
||||||
// If m_refresh_from_block_height is explicitly set to zero we need this to differentiate it from the case that
|
// If m_refresh_from_block_height is explicitly set to zero we need this to differentiate it from the case that
|
||||||
// m_refresh_from_block_height was defaulted to zero.*/
|
// m_refresh_from_block_height was defaulted to zero.*/
|
||||||
|
|
|
@ -104,7 +104,7 @@ namespace tools
|
||||||
m_stop = false;
|
m_stop = false;
|
||||||
m_net_server.add_idle_handler([this](){
|
m_net_server.add_idle_handler([this](){
|
||||||
try {
|
try {
|
||||||
if (m_wallet) m_wallet->refresh();
|
if (m_wallet) m_wallet->refresh(m_trusted_daemon);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
LOG_ERROR("Exception at while refreshing, what=" << ex.what());
|
LOG_ERROR("Exception at while refreshing, what=" << ex.what());
|
||||||
}
|
}
|
||||||
|
@ -2986,7 +2986,7 @@ int main(int argc, char** argv) {
|
||||||
wal->stop();
|
wal->stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
wal->refresh();
|
wal->refresh(command_line::get_arg(*vm, arg_trusted_daemon));
|
||||||
// if we ^C during potentially length load/refresh, there's no server loop yet
|
// if we ^C during potentially length load/refresh, there's no server loop yet
|
||||||
if (quit)
|
if (quit)
|
||||||
{
|
{
|
||||||
|
|
|
@ -143,7 +143,7 @@ bool transactions_flow_test(std::string& working_folder,
|
||||||
uint64_t blocks_fetched = 0;
|
uint64_t blocks_fetched = 0;
|
||||||
bool received_money;
|
bool received_money;
|
||||||
bool ok;
|
bool ok;
|
||||||
if(!w1.refresh(blocks_fetched, received_money, ok))
|
if(!w1.refresh(true, blocks_fetched, received_money, ok))
|
||||||
{
|
{
|
||||||
LOG_ERROR( "failed to refresh source wallet from " << daemon_addr_a );
|
LOG_ERROR( "failed to refresh source wallet from " << daemon_addr_a );
|
||||||
return false;
|
return false;
|
||||||
|
@ -171,11 +171,11 @@ bool transactions_flow_test(std::string& working_folder,
|
||||||
CHECK_AND_ASSERT_MES(daemon_rsp.status == CORE_RPC_STATUS_OK, false, "failed to getrandom_outs.bin");
|
CHECK_AND_ASSERT_MES(daemon_rsp.status == CORE_RPC_STATUS_OK, false, "failed to getrandom_outs.bin");
|
||||||
|
|
||||||
//wait for money, until balance will have enough money
|
//wait for money, until balance will have enough money
|
||||||
w1.refresh(blocks_fetched, received_money, ok);
|
w1.refresh(true, blocks_fetched, received_money, ok);
|
||||||
while(w1.unlocked_balance(0) < amount_to_transfer)
|
while(w1.unlocked_balance(0) < amount_to_transfer)
|
||||||
{
|
{
|
||||||
misc_utils::sleep_no_w(1000);
|
misc_utils::sleep_no_w(1000);
|
||||||
w1.refresh(blocks_fetched, received_money, ok);
|
w1.refresh(true, blocks_fetched, received_money, ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
//lets make a lot of small outs to ourselves
|
//lets make a lot of small outs to ourselves
|
||||||
|
@ -202,7 +202,7 @@ bool transactions_flow_test(std::string& working_folder,
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
misc_utils::sleep_no_w(1000);
|
misc_utils::sleep_no_w(1000);
|
||||||
w1.refresh(blocks_fetched, received_money, ok);
|
w1.refresh(true, blocks_fetched, received_money, ok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//do actual transfer
|
//do actual transfer
|
||||||
|
@ -224,7 +224,7 @@ bool transactions_flow_test(std::string& working_folder,
|
||||||
{
|
{
|
||||||
misc_utils::sleep_no_w(1000);
|
misc_utils::sleep_no_w(1000);
|
||||||
LOG_PRINT_L0("not enough money, waiting for cashback or mining");
|
LOG_PRINT_L0("not enough money, waiting for cashback or mining");
|
||||||
w1.refresh(blocks_fetched, received_money, ok);
|
w1.refresh(true, blocks_fetched, received_money, ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction tx;
|
transaction tx;
|
||||||
|
@ -239,7 +239,7 @@ bool transactions_flow_test(std::string& working_folder,
|
||||||
if(!do_send_money(w1, w2, mix_in_factor, amount_to_tx, tx))
|
if(!do_send_money(w1, w2, mix_in_factor, amount_to_tx, tx))
|
||||||
{
|
{
|
||||||
LOG_PRINT_L0("failed to transfer money, tx: " << get_transaction_hash(tx) << ", refresh and try again" );
|
LOG_PRINT_L0("failed to transfer money, tx: " << get_transaction_hash(tx) << ", refresh and try again" );
|
||||||
w1.refresh(blocks_fetched, received_money, ok);
|
w1.refresh(true, blocks_fetched, received_money, ok);
|
||||||
if(!do_send_money(w1, w2, mix_in_factor, amount_to_tx, tx))
|
if(!do_send_money(w1, w2, mix_in_factor, amount_to_tx, tx))
|
||||||
{
|
{
|
||||||
LOG_PRINT_L0( "failed to transfer money, second chance. tx: " << get_transaction_hash(tx) << ", exit" );
|
LOG_PRINT_L0( "failed to transfer money, second chance. tx: " << get_transaction_hash(tx) << ", exit" );
|
||||||
|
@ -264,7 +264,7 @@ bool transactions_flow_test(std::string& working_folder,
|
||||||
misc_utils::sleep_no_w(DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN*20*1000);//wait two blocks before sync on another wallet on another daemon
|
misc_utils::sleep_no_w(DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN*20*1000);//wait two blocks before sync on another wallet on another daemon
|
||||||
LOG_PRINT_L0( "refreshing...");
|
LOG_PRINT_L0( "refreshing...");
|
||||||
bool recvd_money = false;
|
bool recvd_money = false;
|
||||||
while(w2.refresh(blocks_fetched, recvd_money, ok) && ( (blocks_fetched && recvd_money) || !blocks_fetched ) )
|
while(w2.refresh(true, blocks_fetched, recvd_money, ok) && ( (blocks_fetched && recvd_money) || !blocks_fetched ) )
|
||||||
{
|
{
|
||||||
misc_utils::sleep_no_w(DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN*1000);//wait two blocks before sync on another wallet on another daemon
|
misc_utils::sleep_no_w(DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN*1000);//wait two blocks before sync on another wallet on another daemon
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue