forked from MystenLabs/sui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c9ba193
commit 1d1328e
Showing
5 changed files
with
235 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
[package] | ||
name = "sui-tool" | ||
version = "0.6.0" | ||
authors = ["Mysten Labs <[email protected]>"] | ||
license = "Apache-2.0" | ||
publish = false | ||
edition = "2021" | ||
|
||
[dependencies] | ||
anyhow = { version = "1.0.58", features = ["backtrace"] } | ||
tokio = { version = "1.18.2", features = ["full"] } | ||
tracing = "0.1.35" | ||
clap = { version = "3.1.17", features = ["derive"] } | ||
telemetry-subscribers = { git = "https://github.com/MystenLabs/mysten-infra", rev = "40dae350a699f59f2e296152e02c78765db34e68" } | ||
mysten-network = { git = "https://github.com/MystenLabs/mysten-infra", rev = "40dae350a699f59f2e296152e02c78765db34e68" } | ||
|
||
sui-core = { path = "../sui-core" } | ||
sui-framework = { path = "../sui-framework" } | ||
sui-config = { path = "../sui-config" } | ||
sui-types = { path = "../sui-types" } | ||
sui-json = { path = "../sui-json" } | ||
sui-gateway = { path = "../sui-gateway" } | ||
sui-swarm = { path = "../sui-swarm" } | ||
sui-json-rpc-api = { path = "../sui-json-rpc-api" } | ||
|
||
rustyline = "9.1.2" | ||
rustyline-derive = "0.6.0" | ||
colored = "2.0.0" | ||
unescape = "0.1.0" | ||
shell-words = "1.1.0" | ||
|
||
workspace-hack = { path = "../workspace-hack"} |
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,152 @@ | ||
// Copyright (c) 2022, Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use anyhow::Result; | ||
use std::collections::BTreeMap; | ||
use std::path::PathBuf; | ||
use std::time::Duration; | ||
use sui_config::genesis::Genesis; | ||
|
||
use sui_core::authority_client::{AuthorityAPI, NetworkAuthorityClient}; | ||
use sui_types::{base_types::*, messages::*}; | ||
|
||
use clap::*; | ||
|
||
#[derive(Parser)] | ||
#[clap( | ||
name = "sui-tool", | ||
about = "Debugging utilities for sui", | ||
rename_all = "kebab-case", | ||
author, | ||
version | ||
)] | ||
pub enum ToolCommand { | ||
/// Fetch the same object from all validators | ||
#[clap(name = "fetch-object")] | ||
FetchObject { | ||
#[clap(long, help = "The object ID to fetch")] | ||
id: ObjectID, | ||
|
||
#[clap(long, help = "Fetch object at a specific sequence")] | ||
version: Option<u64>, | ||
|
||
#[clap( | ||
long, | ||
help = "Validator to fetch from - if not specified, all validators are queried" | ||
)] | ||
validator: Option<AuthorityName>, | ||
|
||
#[clap(long = "genesis")] | ||
genesis: PathBuf, | ||
}, | ||
} | ||
|
||
fn make_clients(genesis: PathBuf) -> Result<BTreeMap<AuthorityName, NetworkAuthorityClient>> { | ||
let mut net_config = mysten_network::config::Config::new(); | ||
net_config.connect_timeout = Some(Duration::from_secs(5)); | ||
net_config.request_timeout = Some(Duration::from_secs(5)); | ||
net_config.http2_keepalive_interval = Some(Duration::from_secs(5)); | ||
|
||
let genesis = Genesis::load(genesis)?; | ||
|
||
let mut authority_clients = BTreeMap::new(); | ||
|
||
for validator in genesis.validator_set() { | ||
let channel = net_config.connect_lazy(&validator.network_address)?; | ||
let client = NetworkAuthorityClient::new(channel); | ||
let public_key_bytes = validator.public_key(); | ||
authority_clients.insert(public_key_bytes, client); | ||
} | ||
|
||
Ok(authority_clients) | ||
} | ||
|
||
struct ObjectOutput { | ||
requested_id: ObjectID, | ||
responses: Vec<(AuthorityName, ObjectInfoResponse)>, | ||
} | ||
|
||
impl std::fmt::Display for ObjectOutput { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
writeln!(f, "Object: {}", self.requested_id)?; | ||
|
||
for (name, resp) in &self.responses { | ||
writeln!(f, "-- validator: {:?}", name)?; | ||
|
||
let objref = resp | ||
.requested_object_reference | ||
.as_ref() | ||
.map(|o| format!("{:?}", o)) | ||
.unwrap_or_else(|| "<no object>".into()); | ||
writeln!(f, "---- ref: {}", objref)?; | ||
|
||
let cert = resp | ||
.parent_certificate | ||
.as_ref() | ||
.map(|c| format!("{:?}", c.digest())) | ||
.unwrap_or_else(|| "<genesis>".into()); | ||
writeln!(f, "---- cert: {}", cert)?; | ||
|
||
if let Some(ObjectResponse { lock, .. }) = &resp.object_and_lock { | ||
// TODO maybe show object contents if we can do so meaningfully. | ||
writeln!(f, "---- object: <data>")?; | ||
writeln!( | ||
f, | ||
"---- locked by : {}", | ||
lock.as_ref() | ||
.map(|l| format!("{:?}", l.digest())) | ||
.unwrap_or_else(|| "<not locked>".into()) | ||
)?; | ||
} | ||
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
impl ToolCommand { | ||
pub async fn execute(self) -> Result<(), anyhow::Error> { | ||
match self { | ||
ToolCommand::FetchObject { | ||
id, | ||
validator, | ||
genesis, | ||
version, | ||
} => { | ||
let clients = make_clients(genesis)?; | ||
|
||
let clients = clients.iter().filter(|(name, _)| { | ||
if let Some(v) = validator { | ||
v == **name | ||
} else { | ||
true | ||
} | ||
}); | ||
|
||
let mut output = ObjectOutput { | ||
requested_id: id, | ||
responses: Vec::new(), | ||
}; | ||
|
||
for (name, client) in clients { | ||
let resp = client | ||
.handle_object_info_request(ObjectInfoRequest { | ||
object_id: id, | ||
request_kind: match version { | ||
None => ObjectInfoRequestKind::LatestObjectInfo(None), | ||
Some(v) => ObjectInfoRequestKind::PastObjectInfo( | ||
SequenceNumber::from_u64(v), | ||
), | ||
}, | ||
}) | ||
.await?; | ||
|
||
output.responses.push((*name, resp)); | ||
} | ||
|
||
println!("{}", output); | ||
} | ||
} | ||
|
||
Ok(()) | ||
} | ||
} |
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,24 @@ | ||
// Copyright (c) 2022, Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
extern crate core; | ||
|
||
use clap::*; | ||
use colored::Colorize; | ||
use sui_types::exit_main; | ||
|
||
mod commands; | ||
use commands::ToolCommand; | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
#[cfg(windows)] | ||
colored::control::set_virtual_terminal(true).unwrap(); | ||
|
||
let bin_name = env!("CARGO_BIN_NAME"); | ||
let cmd: ToolCommand = ToolCommand::parse(); | ||
let _guard = telemetry_subscribers::TelemetryConfig::new(bin_name) | ||
.with_env() | ||
.init(); | ||
|
||
exit_main!(cmd.execute().await); | ||
} |