-
Notifications
You must be signed in to change notification settings - Fork 686
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Flat storage] adding debug tool for flat storage #8531
Merged
+393
−1
Merged
Changes from 1 commit
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
611af08
first version of the CLI tool for flat storage
mm-near 7a5027f
put under the compilation flag
mm-near de0afc2
small fixes
mm-near 9f5e9af
Merge branch 'master' into 0207_flat_storage_tool
mm-near 6374590
add proper state root
mm-near 41f099b
review
mm-near e2ad32a
renamed
mm-near 93de344
Merge branch 'master' into 0207_flat_storage_tool
mm-near a721f63
fix
mm-near 9270182
Merge refs/heads/master into 0207_flat_storage_tool
near-bulldozer[bot] 7e619d3
fixed compile issue
mm-near 6ba436c
Merge branch '0207_flat_storage_tool' of github.com:near/nearcore int…
mm-near File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
put under the compilation flag
commit 7a5027f80cfe5d1250a5b4cce9a29d6e5677776a
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,269 @@ | ||
/// Tools for modifying flat storage - should be used only for experimentation & debugging. | ||
use clap::Parser; | ||
use near_chain::{ | ||
flat_storage_creator::FlatStorageShardCreator, types::RuntimeAdapter, ChainStore, | ||
ChainStoreAccess, | ||
}; | ||
use near_epoch_manager::EpochManagerAdapter; | ||
use near_primitives::{state::ValueRef, trie_key::trie_key_parsers::parse_account_id_from_raw_key}; | ||
use near_store::{ | ||
flat_state::store_helper::{self, get_flat_head, get_flat_storage_creation_status}, | ||
Mode, NodeStorage, Store, StoreOpener, | ||
}; | ||
use nearcore::{load_config, NearConfig, NightshadeRuntime}; | ||
use std::{path::PathBuf, sync::Arc, time::Duration}; | ||
use tqdm::tqdm; | ||
|
||
#[derive(Parser)] | ||
pub struct FlatStorageCommand { | ||
#[clap(subcommand)] | ||
subcmd: SubCommand, | ||
} | ||
|
||
#[derive(Parser)] | ||
#[clap(subcommand_required = true, arg_required_else_help = true)] | ||
enum SubCommand { | ||
/// View the current state of flat storage | ||
View, | ||
|
||
/// Reset the flat storage state (remove all the contents) | ||
Reset(ResetCmd), | ||
|
||
/// Init the flat storage state, by copying from trie | ||
Init(InitCmd), | ||
|
||
/// Verify flat storage state | ||
mm-near marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Verify(VerifyCmd), | ||
|
||
/// Temporary command to set the store version (useful as long flat | ||
/// storage is enabled only during nightly with separate DB version). | ||
SetStoreVersion(SetStoreVersionCmd), | ||
} | ||
|
||
#[derive(Parser)] | ||
pub struct SetStoreVersionCmd { | ||
version: u32, | ||
} | ||
|
||
#[derive(Parser)] | ||
pub struct ResetCmd { | ||
shard_id: u64, | ||
} | ||
|
||
#[derive(Parser)] | ||
|
||
pub struct InitCmd { | ||
shard_id: u64, | ||
|
||
#[clap(default_value = "3")] | ||
num_threads: usize, | ||
} | ||
|
||
#[derive(Parser)] | ||
pub struct VerifyCmd { | ||
shard_id: u64, | ||
} | ||
|
||
impl FlatStorageCommand { | ||
fn get_db( | ||
opener: &StoreOpener, | ||
home_dir: &PathBuf, | ||
near_config: &NearConfig, | ||
mode: Mode, | ||
) -> (NodeStorage, Arc<NightshadeRuntime>, ChainStore, Store) { | ||
let node_storage = opener.open_in_mode(mode).unwrap(); | ||
let hot_runtime = Arc::new(NightshadeRuntime::from_config( | ||
home_dir, | ||
node_storage.get_hot_store(), | ||
&near_config, | ||
)); | ||
let chain_store = ChainStore::new(node_storage.get_hot_store(), 0, false); | ||
let hot_store = node_storage.get_hot_store(); | ||
(node_storage, hot_runtime, chain_store, hot_store) | ||
} | ||
|
||
pub fn run(&self, home_dir: &PathBuf) -> anyhow::Result<()> { | ||
let near_config = | ||
load_config(home_dir, near_chain_configs::GenesisValidationMode::Full).unwrap(); | ||
let opener = NodeStorage::opener(home_dir, &near_config.config.store, None); | ||
|
||
match &self.subcmd { | ||
SubCommand::View => { | ||
let (_, hot_runtime, chain_store, hot_store) = | ||
Self::get_db(&opener, home_dir, &near_config, near_store::Mode::ReadOnly); | ||
let tip = chain_store.final_head().unwrap(); | ||
let shards = hot_runtime.num_shards(&tip.epoch_id).unwrap(); | ||
println!("DB version: {:?}", hot_store.get_db_version()); | ||
println!("Current final tip @{:?} - shards: {:?}", tip.height, shards); | ||
|
||
for shard in 0..shards { | ||
let head_hash = get_flat_head(&hot_store, shard); | ||
if let Some(head_hash) = head_hash { | ||
let head_header = chain_store.get_block_header(&head_hash); | ||
let creation_status = get_flat_storage_creation_status(&hot_store, shard); | ||
println!( | ||
"Shard: {:?} - flat storage @{:?} Details: {:?}", | ||
shard, | ||
head_header.map(|header| header.height()), | ||
creation_status | ||
); | ||
} else { | ||
println!("Shard: {:?} - no flat storage.", shard) | ||
} | ||
} | ||
} | ||
SubCommand::SetStoreVersion(set_version) => { | ||
let rw_storage = opener.open_in_mode(near_store::Mode::ReadWriteExisting).unwrap(); | ||
let rw_store = rw_storage.get_hot_store(); | ||
println!("Setting storage DB version to: {:?}", set_version.version); | ||
rw_store.set_db_version(set_version.version)?; | ||
} | ||
SubCommand::Reset(reset_cmd) => { | ||
let (_, rw_hot_runtime, rw_chain_store, _) = Self::get_db( | ||
&opener, | ||
home_dir, | ||
&near_config, | ||
near_store::Mode::ReadWriteExisting, | ||
); | ||
let tip = rw_chain_store.final_head().unwrap(); | ||
|
||
// TODO: there should be a method that 'loads' the current flat storage state based on Storage. | ||
rw_hot_runtime.create_flat_storage_state_for_shard( | ||
reset_cmd.shard_id, | ||
tip.height, | ||
&rw_chain_store, | ||
); | ||
|
||
rw_hot_runtime | ||
.remove_flat_storage_state_for_shard(reset_cmd.shard_id, &tip.epoch_id)?; | ||
} | ||
SubCommand::Init(init_cmd) => { | ||
let (_, rw_hot_runtime, rw_chain_store, rw_hot_store) = Self::get_db( | ||
&opener, | ||
home_dir, | ||
&near_config, | ||
near_store::Mode::ReadWriteExisting, | ||
); | ||
|
||
let tip = rw_chain_store.final_head().unwrap(); | ||
|
||
let mut creator = | ||
FlatStorageShardCreator::new(init_cmd.shard_id, tip.height, rw_hot_runtime); | ||
let pool = rayon::ThreadPoolBuilder::new() | ||
.num_threads(init_cmd.num_threads) | ||
.build() | ||
.unwrap(); | ||
|
||
loop { | ||
let status = creator.update_status(&rw_chain_store, &pool)?; | ||
if status { | ||
break; | ||
} | ||
let current_status = | ||
get_flat_storage_creation_status(&rw_hot_store, init_cmd.shard_id); | ||
println!("Status: {:?}", current_status); | ||
|
||
std::thread::sleep(Duration::from_secs(1)); | ||
} | ||
|
||
println!("Flat storage initialization finished."); | ||
} | ||
SubCommand::Verify(verify_cmd) => { | ||
let (_, hot_runtime, chain_store, hot_store) = | ||
Self::get_db(&opener, home_dir, &near_config, near_store::Mode::ReadOnly); | ||
|
||
let head_hash = get_flat_head(&hot_store, verify_cmd.shard_id).expect(&format!( | ||
"Flat storage head missing for shard {:?}.", | ||
verify_cmd.shard_id | ||
)); | ||
let block_header = chain_store.get_block_header(&head_hash).unwrap(); | ||
let block = chain_store.get_block(&head_hash).unwrap(); | ||
println!( | ||
"Verifying flat storage for shard {:?} - flat head @{:?} ({:?})", | ||
verify_cmd.shard_id, | ||
block_header.height(), | ||
block_header.hash() | ||
); | ||
let chunks_collection = block.chunks(); | ||
let shard_chunk_header = | ||
chunks_collection.get(verify_cmd.shard_id as usize).unwrap(); | ||
// TODO: this might be wrong.. | ||
let state_root = shard_chunk_header.prev_state_root(); | ||
|
||
println!("Verifying using the {:?} as state_root", state_root); | ||
let tip = chain_store.final_head().unwrap(); | ||
|
||
hot_runtime.create_flat_storage_state_for_shard( | ||
verify_cmd.shard_id, | ||
tip.height, | ||
&chain_store, | ||
); | ||
|
||
let trie = hot_runtime | ||
.get_view_trie_for_shard(verify_cmd.shard_id, &head_hash, state_root) | ||
.unwrap(); | ||
|
||
let shard_layout = hot_runtime.get_shard_layout(block_header.epoch_id()).unwrap(); | ||
|
||
let all_entries = store_helper::iter_flat_state_entries( | ||
mm-near marked this conversation as resolved.
Show resolved
Hide resolved
|
||
shard_layout, | ||
verify_cmd.shard_id, | ||
&hot_store, | ||
None, | ||
None, | ||
); | ||
|
||
let trie_iter = trie.iter().unwrap().filter(|entry| { | ||
mm-near marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let result_copy = &entry.clone().unwrap().0; | ||
let result = &result_copy[..]; | ||
parse_account_id_from_raw_key(result).unwrap().is_some() | ||
}); | ||
|
||
let mut verified = 0; | ||
let mut success = true; | ||
for (item_trie, item_flat) in tqdm(std::iter::zip(trie_iter, all_entries)) { | ||
let value_ref = ValueRef::decode((*item_flat.1).try_into().unwrap()); | ||
verified += 1; | ||
|
||
let item_trie = item_trie.unwrap(); | ||
if item_trie.0 != *item_flat.0 { | ||
println!( | ||
"Different keys {:?} in trie, {:?} in flat. ", | ||
mm-near marked this conversation as resolved.
Show resolved
Hide resolved
|
||
item_trie.0, item_flat.0 | ||
); | ||
success = false; | ||
break; | ||
} | ||
if item_trie.1.len() != value_ref.length as usize { | ||
println!( | ||
"Wrong values for key: {:?} length trie: {:?} vs {:?}", | ||
mm-near marked this conversation as resolved.
Show resolved
Hide resolved
|
||
item_trie.0, | ||
item_trie.1.len(), | ||
value_ref.length | ||
); | ||
success = false; | ||
break; | ||
} | ||
|
||
if near_primitives::hash::hash(&item_trie.1) != value_ref.hash { | ||
println!( | ||
"Wrong hash for key: {:?} length trie: {:?} vs {:?}", | ||
mm-near marked this conversation as resolved.
Show resolved
Hide resolved
|
||
item_trie.0, | ||
near_primitives::hash::hash(&item_trie.1), | ||
value_ref.hash | ||
); | ||
success = false; | ||
break; | ||
} | ||
} | ||
if success { | ||
println!("Success - verified {:?} nodes", verified); | ||
} else { | ||
println!("FAILED - on node {:?}", verified); | ||
} | ||
} | ||
} | ||
|
||
Ok(()) | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cargo fmt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.