Reduce inbound concurrency to limit memory usage

Inbound malicious blocks can use a large amount of RAM when
deserialized. Limit inbound concurrency, so that the total amount
of RAM remains small.
This commit is contained in:
teor 2021-03-11 11:22:42 +10:00 committed by Deirdre Connolly
parent 475deaf655
commit c6358b157c
1 changed files with 21 additions and 4 deletions

View File

@ -23,10 +23,27 @@ type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
/// The maximum number of concurrent inbound download and verify tasks.
///
/// Set to one and a half checkpoint intervals, so that the inbound queue can
/// hold a complete checkpoint interval, if needed. We expect the syncer to
/// download and verify checkpoints, so this bound might never be reached.
const MAX_INBOUND_CONCURRENCY: usize = zebra_consensus::MAX_CHECKPOINT_HEIGHT_GAP * 3 / 2;
/// We expect the syncer to download and verify checkpoints, so this bound
/// can be small.
///
/// ## Security
///
/// We use a small concurrency limit, to prevent memory denial-of-service
/// attacks.
///
/// The maximum block size is 2 million bytes. A deserialized malicious
/// block with ~225_000 transparent outputs can take up 9MB of RAM. As of
/// February 2021, a growing `Vec` can allocate up to 2x its current length,
/// leading to an overall memory usage of 18MB per malicious block. (See
/// #1880 for more details.)
///
/// Malicious blocks will eventually timeout or fail contextual validation.
/// Once validation fails, the block is dropped, and its memory is deallocated.
///
/// Since Zebra keeps an `inv` index, inbound downloads for malicious blocks
/// will be directed to the malicious node that originally gossiped the hash.
/// Therefore, this attack can be carried out by a single malicious node.
const MAX_INBOUND_CONCURRENCY: usize = 10;
/// The action taken in response to a peer's gossipped block hash.
pub enum DownloadAction {