From 6a00c11a99d6ae3a2aba6818f3d6d77abc4f8af2 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Mon, 11 Apr 2022 17:41:23 +0200 Subject: [PATCH] chain: allow chain_tail to be set w/o tail being set on archival nodes (#6563) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 6be2e0e8e: ‘gc partial chunks on archival nodes (#6439)’, archival nodes set chunk_tail without setting tail. However, store validation expects both of those to be set or unset. Change the code to allow unset tail on archival nodes. Issue: https://github.com/near/nearcore/issues/6242 --- chain/chain/src/store.rs | 1 + chain/chain/src/store_validator.rs | 6 +++++- chain/chain/src/store_validator/validate.rs | 8 +++++--- chain/client/src/client_actor.rs | 1 + chain/client/src/view_client.rs | 8 ++++++++ nearcore/src/lib.rs | 3 ++- test-utils/store-validator/src/main.rs | 1 + 7 files changed, 23 insertions(+), 5 deletions(-) diff --git a/chain/chain/src/store.rs b/chain/chain/src/store.rs index 10c41b88c1d..3a2768caad0 100644 --- a/chain/chain/src/store.rs +++ b/chain/chain/src/store.rs @@ -3664,6 +3664,7 @@ mod tests { genesis.clone(), chain.runtime_adapter.clone(), chain.store().store().clone(), + false, ); store_validator.validate(); println!("errors = {:?}", store_validator.errors); diff --git a/chain/chain/src/store_validator.rs b/chain/chain/src/store_validator.rs index 70342b2f11a..67251462d52 100644 --- a/chain/chain/src/store_validator.rs +++ b/chain/chain/src/store_validator.rs @@ -78,6 +78,7 @@ pub struct StoreValidator { inner: StoreValidatorCache, timeout: Option, start_time: Instant, + pub is_archival: bool, pub errors: Vec, tests: u64, @@ -89,6 +90,7 @@ impl StoreValidator { config: GenesisConfig, runtime_adapter: Arc, store: Store, + is_archival: bool, ) -> Self { StoreValidator { me, @@ -98,6 +100,7 @@ impl StoreValidator { inner: StoreValidatorCache::new(), timeout: None, start_time: Clock::instant(), + is_archival, errors: vec![], tests: 0, } @@ -337,6 +340,7 @@ impl StoreValidator { } Ok(()) } + pub fn validate(&mut self) { self.start_time = Clock::instant(); @@ -425,7 +429,7 @@ mod tests { true, ) .unwrap(); - (chain, StoreValidator::new(None, genesis, runtime_adapter, store)) + (chain, StoreValidator::new(None, genesis, runtime_adapter, store, false)) } #[test] diff --git a/chain/chain/src/store_validator/validate.rs b/chain/chain/src/store_validator/validate.rs index 3b16343d35e..aa89ecca6b2 100644 --- a/chain/chain/src/store_validator/validate.rs +++ b/chain/chain/src/store_validator/validate.rs @@ -124,9 +124,11 @@ pub(crate) fn head_tail_validity(sv: &mut StoreValidator) -> Result<(), StoreVal sv.store.get_ser::(ColBlockMisc, FORK_TAIL_KEY), "Can't get Chunk Tail from storage" ); - if tail_db.is_none() && chunk_tail_db.is_some() || tail_db.is_some() && chunk_tail_db.is_none() - { - err!("Tail is {:?} and Chunk Tail is {:?}", tail_db, chunk_tail_db); + if tail_db.is_none() != chunk_tail_db.is_none() { + // Archival nodes can have chunk_tail set without tail being set. + if !sv.is_archival || chunk_tail_db.is_none() { + err!("Tail is {:?} and Chunk Tail is {:?}", tail_db, chunk_tail_db); + } } if tail_db.is_some() && fork_tail_db.is_none() { err!("Tail is {:?} but fork tail is None", tail_db); diff --git a/chain/client/src/client_actor.rs b/chain/client/src/client_actor.rs index 99fb2ead8e2..155487bff07 100644 --- a/chain/client/src/client_actor.rs +++ b/chain/client/src/client_actor.rs @@ -356,6 +356,7 @@ impl ClientActor { genesis, self.client.runtime_adapter.clone(), self.client.chain.store().store().clone(), + self.adv.read().unwrap().is_archival, ); store_validator.set_timeout(timeout); store_validator.validate(); diff --git a/chain/client/src/view_client.rs b/chain/client/src/view_client.rs index 5bd2e85e870..f3e51fdb31b 100644 --- a/chain/client/src/view_client.rs +++ b/chain/client/src/view_client.rs @@ -87,6 +87,14 @@ pub struct AdversarialControls { pub adv_disable_header_sync: bool, pub adv_disable_doomslug: bool, pub adv_sync_height: Option, + pub is_archival: bool, +} + +#[cfg(feature = "test_features")] +impl AdversarialControls { + pub fn new(is_archival: bool) -> Self { + Self { is_archival, ..Self::default() } + } } /// View client provides currently committed (to the storage) view of the current chain and state. diff --git a/nearcore/src/lib.rs b/nearcore/src/lib.rs index b83c2e47e3a..9cae09dc837 100644 --- a/nearcore/src/lib.rs +++ b/nearcore/src/lib.rs @@ -415,7 +415,8 @@ pub fn start_with_config_and_synchronization( let node_id = PeerId::new(config.network_config.public_key.clone().into()); let network_adapter = Arc::new(NetworkRecipient::default()); #[cfg(feature = "test_features")] - let adv = Arc::new(std::sync::RwLock::new(AdversarialControls::default())); + let adv = + Arc::new(std::sync::RwLock::new(AdversarialControls::new(config.client_config.archive))); let view_client = start_view_client( config.validator_signer.as_ref().map(|signer| signer.validator_id().clone()), diff --git a/test-utils/store-validator/src/main.rs b/test-utils/store-validator/src/main.rs index 1af9712d22e..4d6d4643116 100644 --- a/test-utils/store-validator/src/main.rs +++ b/test-utils/store-validator/src/main.rs @@ -48,6 +48,7 @@ fn main() { near_config.genesis.config, runtime_adapter.clone(), store, + false, ); store_validator.validate();