From 923adf0fe57d3ed147511e2784fb072757d8e6c4 Mon Sep 17 00:00:00 2001 From: hashmap Date: Tue, 3 Apr 2018 01:10:30 +0200 Subject: [PATCH] Fix header_by_height (#922) Currently for fast sync index header_by_height is created only for headers above the horizon --- api/src/handlers.rs | 20 ++++++++++++++++++++ chain/src/chain.rs | 7 +++++++ chain/src/store.rs | 9 +++++++-- chain/src/types.rs | 3 +++ grin/tests/simulnet.rs | 3 +++ 5 files changed, 40 insertions(+), 2 deletions(-) diff --git a/api/src/handlers.rs b/api/src/handlers.rs index 8be5ddfa8..a6a4c4ed2 100644 --- a/api/src/handlers.rs +++ b/api/src/handlers.rs @@ -419,6 +419,21 @@ impl Handler for ChainValidationHandler { } } +/// Temporary - fix header by height index. +/// POST /v1/chain/height-index +pub struct HeaderByHeightHandler { + pub chain: Weak, +} + +impl Handler for HeaderByHeightHandler { + fn handle(&self, _req: &mut Request) -> IronResult { + match w(&self.chain).rebuild_header_by_height() { + Ok(_) => Ok(Response::with((status::Ok, ""))), + Err(_) => Ok(Response::with((status::InternalServerError, ""))), + } + } +} + /// Chain compaction handler. Trigger a compaction of the chain state to regain /// storage space. /// GET /v1/chain/compact @@ -650,6 +665,9 @@ pub fn start_rest_apis( let chain_compact_handler = ChainCompactHandler { chain: chain.clone(), }; + let header_height_handler = HeaderByHeightHandler { + chain: chain.clone(), + }; let chain_validation_handler = ChainValidationHandler { chain: chain.clone(), }; @@ -686,6 +704,7 @@ pub fn start_rest_apis( "get chain/compact".to_string(), "get chain/validate".to_string(), "get chain/outputs".to_string(), + "post chain/height-index".to_string(), "get status".to_string(), "get txhashset/roots".to_string(), "get txhashset/lastoutputs?n=10".to_string(), @@ -708,6 +727,7 @@ pub fn start_rest_apis( chain_compact: get "/chain/compact" => chain_compact_handler, chain_validate: get "/chain/validate" => chain_validation_handler, chain_outputs: get "/chain/outputs/*" => output_handler, + header_height: post "/chain/height-index" => header_height_handler, status: get "/status" => status_handler, txhashset_roots: get "/txhashset/*" => txhashset_handler, pool_info: get "/pool" => pool_info_handler, diff --git a/chain/src/chain.rs b/chain/src/chain.rs index 9ddf20108..df19b338a 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -750,4 +750,11 @@ impl Chain { .get_block_pmmr_file_metadata(h) .map_err(|e| Error::StoreErr(e, "retrieve block pmmr metadata".to_owned())) } + + pub fn rebuild_header_by_height(&self) -> Result<(), Error> { + let head = self.head_header()?; + self.store + .build_by_height_index(&head, true) + .map_err(|e| Error::StoreErr(e, "rebuilf header by height index".to_owned())) + } } diff --git a/chain/src/store.rs b/chain/src/store.rs index 15141d1ef..85c03fbb1 100644 --- a/chain/src/store.rs +++ b/chain/src/store.rs @@ -229,14 +229,19 @@ impl ChainStore for ChainKVStore { for n in header.height..old_tip.height { self.delete_header_by_height(n)?; } + self.build_by_height_index(header, false) + } + fn build_by_height_index(&self, header: &BlockHeader, force: bool) -> Result<(), Error> { self.save_header_height(&header)?; if header.height > 0 { let mut prev_header = self.get_block_header(&header.previous)?; while prev_header.height > 0 { - if let Ok(_) = self.is_on_current_chain(&prev_header) { - break; + if !force { + if let Ok(_) = self.is_on_current_chain(&prev_header) { + break; + } } self.save_header_height(&prev_header)?; diff --git a/chain/src/types.rs b/chain/src/types.rs index 373ddcd91..9085c71f5 100644 --- a/chain/src/types.rs +++ b/chain/src/types.rs @@ -330,6 +330,9 @@ pub trait ChainStore: Send + Sync { /// the consistency of the height chain in store by assuring previous /// headers are also at their respective heights. fn setup_height(&self, bh: &BlockHeader, old_tip: &Tip) -> Result<(), store::Error>; + + /// Similar to setup_height but without handling fork + fn build_by_height_index(&self, header: &BlockHeader, force: bool) -> Result<(), store::Error>; } /// Single serializable struct to hold metadata about all PMMR file position diff --git a/grin/tests/simulnet.rs b/grin/tests/simulnet.rs index 594b68e3e..a26232d95 100644 --- a/grin/tests/simulnet.rs +++ b/grin/tests/simulnet.rs @@ -265,6 +265,9 @@ fn simulate_fast_sync() { while s2.head().height != s2.header_head().height || s2.head().height < 20 { thread::sleep(time::Duration::from_millis(1000)); } + s2.chain.rebuild_header_by_height(); + let h2 = s2.chain.get_header_by_height(1).unwrap(); + s1.stop(); s2.stop(); }