diff --git a/crates/sui-tool/src/commands.rs b/crates/sui-tool/src/commands.rs index 81ef9289e8bdb..e9fbdcd20f27b 100644 --- a/crates/sui-tool/src/commands.rs +++ b/crates/sui-tool/src/commands.rs @@ -21,6 +21,9 @@ use futures::stream::StreamExt; use clap::*; use sui_core::authority::MAX_ITEMS_LIMIT; +use sui_types::messages_checkpoint::{ + CheckpointRequest, CheckpointResponse, CheckpointSequenceNumber, +}; use sui_types::object::ObjectFormatOptions; #[derive(Parser)] @@ -122,16 +125,26 @@ pub enum ToolCommand { #[clap(long = "genesis")] genesis: PathBuf, }, + /// Fetch authenticated checkpoint information at a specific sequence number. + /// If sequence number is not specified, get the latest authenticated checkpoint. + #[clap(name = "fetch-checkpoint")] + FetchAuthenticatedCheckpoint { + #[clap(long = "genesis")] + genesis: PathBuf, + #[clap( + long, + help = "Fetch authenticated checkpoint at a specific sequence number" + )] + sequence_number: Option, + }, } -fn make_clients(genesis: PathBuf) -> Result> { +fn make_clients(genesis: &Genesis) -> Result> { 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() { @@ -401,7 +414,8 @@ impl ToolCommand { genesis, len, } => { - let clients = make_clients(genesis)?; + let genesis = Genesis::load(genesis)?; + let clients = make_clients(&genesis)?; let clients: Vec<_> = clients .iter() @@ -445,7 +459,8 @@ impl ToolCommand { concise, no_header, } => { - let clients = make_clients(genesis)?; + let genesis = Genesis::load(genesis)?; + let clients = make_clients(&genesis)?; let responses = join_all( clients @@ -479,7 +494,8 @@ impl ToolCommand { } } ToolCommand::FetchTransaction { genesis, digest } => { - let clients = make_clients(genesis)?; + let genesis = Genesis::load(genesis)?; + let clients = make_clients(&genesis)?; let responses = join_all(clients.iter().map(|(name, client)| async { let result = client @@ -499,16 +515,43 @@ impl ToolCommand { None => print_db_all_tables(path)?, } } - ToolCommand::DumpValidators { genesis } => { - let genesis = Genesis::load(genesis).unwrap(); + let genesis = Genesis::load(genesis)?; println!("{:#?}", genesis.validator_set()); } - ToolCommand::DumpGenesis { genesis } => { - let genesis = Genesis::load(genesis).unwrap(); + let genesis = Genesis::load(genesis)?; println!("{:#?}", genesis); } + ToolCommand::FetchAuthenticatedCheckpoint { + genesis, + sequence_number, + } => { + let genesis = Genesis::load(genesis)?; + let clients = make_clients(&genesis)?; + let committee = genesis.committee()?; + + for (name, client) in clients { + let resp = client + .handle_checkpoint(CheckpointRequest::authenticated(sequence_number, true)) + .await + .unwrap(); + println!("Validator: {:?}\n", name); + match resp { + CheckpointResponse::AuthenticatedCheckpoint { + checkpoint, + contents, + } => { + println!("Checkpoint: {:?}\n", checkpoint); + println!("Content: {:?}\n", contents); + if let Some(c) = checkpoint { + c.verify(&committee, contents.as_ref())?; + } + } + _ => unreachable!(), + } + } + } }; Ok(()) } diff --git a/crates/sui-types/src/messages_checkpoint.rs b/crates/sui-types/src/messages_checkpoint.rs index 7e8809e2d042c..2642cbf957b9a 100644 --- a/crates/sui-types/src/messages_checkpoint.rs +++ b/crates/sui-types/src/messages_checkpoint.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use std::collections::{BTreeMap, BTreeSet, HashSet}; -use std::fmt::{Display, Formatter}; +use std::fmt::{Debug, Display, Formatter}; use std::slice::Iter; use crate::base_types::ExecutionDigests; @@ -217,13 +217,11 @@ pub struct CheckpointSummaryEnvelope { pub auth_signature: S, } -impl Display for SignedCheckpointSummary { +impl Display for CheckpointSummaryEnvelope { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - writeln!( - f, - "SignedCheckpointSummary {{ summary: {}, signature: {} }}", - self.summary, self.auth_signature, - ) + writeln!(f, "{}", self.summary)?; + writeln!(f, "Signature: {:?}", self.auth_signature)?; + Ok(()) } } @@ -302,16 +300,6 @@ impl SignedCheckpointSummary { pub type CertifiedCheckpointSummary = CheckpointSummaryEnvelope; -impl Display for CertifiedCheckpointSummary { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - writeln!( - f, - "CertifiedCheckpointSummary {{ summary: {}, signature: {} }}", - self.summary, self.auth_signature, - ) - } -} - impl CertifiedCheckpointSummary { /// Aggregate many checkpoint signatures to form a checkpoint certificate. pub fn aggregate(