From 2237f42144c5463de045df9fa96b213fc7158171 Mon Sep 17 00:00:00 2001 From: Yeastplume Date: Fri, 31 Dec 2021 09:47:04 +0000 Subject: [PATCH] Handle attempts to get block headers at invalid heights (#3683) * handle attempts to get block headers at invalid heights * compare requested height against header pmmr size * gte --- chain/src/error.rs | 4 ++++ chain/src/txhashset/txhashset.rs | 3 +++ servers/src/grin/server.rs | 12 +++++++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/chain/src/error.rs b/chain/src/error.rs index a110d9763..b5d1bbf1f 100644 --- a/chain/src/error.rs +++ b/chain/src/error.rs @@ -135,6 +135,10 @@ pub enum ErrorKind { /// Error from underlying block handling #[fail(display = "Block Validation Error: {:?}", _0)] Block(block::Error), + /// Attempt to retrieve a header at a height greater than + /// the max allowed by u64 limits + #[fail(display = "Invalid Header Height: {}", _0)] + InvalidHeaderHeight(u64), /// Anything else #[fail(display = "Other Error: {}", _0)] Other(String), diff --git a/chain/src/txhashset/txhashset.rs b/chain/src/txhashset/txhashset.rs index 6ee077435..8263b8e3d 100644 --- a/chain/src/txhashset/txhashset.rs +++ b/chain/src/txhashset/txhashset.rs @@ -110,6 +110,9 @@ impl PMMRHandle { /// Get the header hash at the specified height based on the current header MMR state. pub fn get_header_hash_by_height(&self, height: u64) -> Result { + if height >= self.size { + return Err(ErrorKind::InvalidHeaderHeight(height).into()); + } let pos = pmmr::insertion_to_pmmr_index(height); let header_pmmr = ReadonlyPMMR::at(&self.backend, self.size); if let Some(entry) = header_pmmr.get_data(pos) { diff --git a/servers/src/grin/server.rs b/servers/src/grin/server.rs index 5fa105118..c66190776 100644 --- a/servers/src/grin/server.rs +++ b/servers/src/grin/server.rs @@ -454,9 +454,15 @@ impl Server { // We need to query again for the actual block hash, as // the difficulty iterator doesn't contain enough info to // create a hash - let block_hash = match self.chain.get_header_by_height(height as u64) { - Ok(h) => h.hash(), - Err(_) => ZERO_HASH, + // The diff iterator returns 59 block headers 'before' 0 to give callers + // enough detail to calculate initial block difficulties. Ignore these. + let block_hash = if height < 0 { + ZERO_HASH + } else { + match self.chain.get_header_by_height(height as u64) { + Ok(h) => h.hash(), + Err(_) => ZERO_HASH, + } }; DiffBlock {