wallet2: fix spurious reorg detection with untrusted nodes
When forced to deal with an untrusted node, a wallet will quantize its current height to disguise the real height to the adversary, to try and minimize the daemon's ability to distinguish returning wallets. Daemons will thus return more blocks than the wallet needs, starting from earlier in the chain. These extra blocks will be disregarded by the wallet, which had already scanned them. However, for the purposes of reorg size detection, the wallet assumes all blocks the daemon sends are different, which is only correct if the wallet hasn't been coy, which is only the case for trusted daemons (which you should use). This causes an issue when the size of this "fake reorg" is above the sanity check threshold at which the wallet refuses a reorg. To fix this, the reorg size check is moved later on, when the reorg is about to actually happen, after the wallet has checked which blocks are actually different from the ones it expects.
This commit is contained in:
parent
8349cfe4a6
commit
fde7c96b5c
|
@ -2882,6 +2882,11 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cry
|
||||||
" (height " + std::to_string(start_height) + "), local block id at this height: " +
|
" (height " + std::to_string(start_height) + "), local block id at this height: " +
|
||||||
string_tools::pod_to_hex(m_blockchain[current_index]));
|
string_tools::pod_to_hex(m_blockchain[current_index]));
|
||||||
|
|
||||||
|
const uint64_t reorg_depth = m_blockchain.size() - current_index;
|
||||||
|
THROW_WALLET_EXCEPTION_IF(reorg_depth > m_max_reorg_depth, error::reorg_depth_error,
|
||||||
|
tr("reorg exceeds maximum allowed depth, use 'set max-reorg-depth N' to allow it, reorg depth: ") +
|
||||||
|
std::to_string(reorg_depth));
|
||||||
|
|
||||||
detach_blockchain(current_index, output_tracker_cache);
|
detach_blockchain(current_index, output_tracker_cache);
|
||||||
process_new_blockchain_entry(bl, blocks[i], parsed_blocks[i], bl_id, current_index, tx_cache_data, tx_cache_data_offset, output_tracker_cache);
|
process_new_blockchain_entry(bl, blocks[i], parsed_blocks[i], bl_id, current_index, tx_cache_data, tx_cache_data_offset, output_tracker_cache);
|
||||||
}
|
}
|
||||||
|
@ -3532,15 +3537,6 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
|
||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
|
|
||||||
if (!next_blocks.empty())
|
|
||||||
{
|
|
||||||
const uint64_t expected_start_height = std::max(static_cast<uint64_t>(m_blockchain.size()), uint64_t(1)) - 1;
|
|
||||||
const uint64_t reorg_depth = expected_start_height - std::min(expected_start_height, next_blocks_start_height);
|
|
||||||
THROW_WALLET_EXCEPTION_IF(reorg_depth > m_max_reorg_depth, error::reorg_depth_error,
|
|
||||||
tr("reorg exceeds maximum allowed depth, use 'set max-reorg-depth N' to allow it, reorg depth: ") +
|
|
||||||
std::to_string(reorg_depth));
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we've got at least 10 blocks to refresh, assume we're starting
|
// if we've got at least 10 blocks to refresh, assume we're starting
|
||||||
// a long refresh, and setup a tracking output cache if we need to
|
// a long refresh, and setup a tracking output cache if we need to
|
||||||
if (m_track_uses && (!output_tracker_cache || output_tracker_cache->empty()) && next_blocks.size() >= 10)
|
if (m_track_uses && (!output_tracker_cache || output_tracker_cache->empty()) && next_blocks.size() >= 10)
|
||||||
|
|
Loading…
Reference in New Issue