From 6deaf649eff9363b506e8f62ede4e5914b436571 Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Wed, 29 Apr 2020 22:55:33 -0600 Subject: [PATCH] Add commitment Root variant, and add fleshed out --commitment arg to Cli (#9806) automerge --- clap-utils/src/commitment.rs | 17 ++++ clap-utils/src/input_parsers.rs | 10 +++ clap-utils/src/lib.rs | 1 + cli/src/cluster_query.rs | 147 +++++++++----------------------- cli/src/vote.rs | 24 ++---- core/src/rpc.rs | 8 +- docs/src/apps/jsonrpc-api.md | 7 +- sdk/src/commitment_config.rs | 7 ++ 8 files changed, 93 insertions(+), 128 deletions(-) create mode 100644 clap-utils/src/commitment.rs diff --git a/clap-utils/src/commitment.rs b/clap-utils/src/commitment.rs new file mode 100644 index 00000000000000..b7e0fa4cf7e702 --- /dev/null +++ b/clap-utils/src/commitment.rs @@ -0,0 +1,17 @@ +use crate::ArgConstant; +use clap::Arg; + +pub const COMMITMENT_ARG: ArgConstant<'static> = ArgConstant { + name: "commitment", + long: "commitment", + help: "Return information at the selected commitment level", +}; + +pub fn commitment_arg<'a, 'b>() -> Arg<'a, 'b> { + Arg::with_name(COMMITMENT_ARG.name) + .long(COMMITMENT_ARG.long) + .takes_value(true) + .possible_values(&["default", "max", "recent", "root"]) + .value_name("COMMITMENT_LEVEL") + .help(COMMITMENT_ARG.help) +} diff --git a/clap-utils/src/input_parsers.rs b/clap-utils/src/input_parsers.rs index aaa4eeb12f1fcf..cddf0a65a909e8 100644 --- a/clap-utils/src/input_parsers.rs +++ b/clap-utils/src/input_parsers.rs @@ -7,6 +7,7 @@ use clap::ArgMatches; use solana_remote_wallet::remote_wallet::RemoteWalletManager; use solana_sdk::{ clock::UnixTimestamp, + commitment_config::CommitmentConfig, native_token::sol_to_lamports, pubkey::Pubkey, signature::{read_keypair_file, Keypair, Signature, Signer}, @@ -177,6 +178,15 @@ pub fn lamports_of_sol(matches: &ArgMatches<'_>, name: &str) -> Option { value_of(matches, name).map(sol_to_lamports) } +pub fn commitment_of(matches: &ArgMatches<'_>, name: &str) -> Option { + matches.value_of(name).map(|value| match value { + "max" => CommitmentConfig::max(), + "recent" => CommitmentConfig::recent(), + "root" => CommitmentConfig::root(), + _ => CommitmentConfig::default(), + }) +} + #[cfg(test)] mod tests { use super::*; diff --git a/clap-utils/src/lib.rs b/clap-utils/src/lib.rs index 37926d6fbe644c..d24beb73e4226c 100644 --- a/clap-utils/src/lib.rs +++ b/clap-utils/src/lib.rs @@ -42,6 +42,7 @@ impl std::fmt::Debug for DisplayError { } } +pub mod commitment; pub mod input_parsers; pub mod input_validators; pub mod keypair; diff --git a/cli/src/cluster_query.rs b/cli/src/cluster_query.rs index 9868299c5769fc..ff3cbf1c0107b5 100644 --- a/cli/src/cluster_query.rs +++ b/cli/src/cluster_query.rs @@ -10,7 +10,12 @@ use chrono::{DateTime, NaiveDateTime, SecondsFormat, Utc}; use clap::{value_t, value_t_or_exit, App, Arg, ArgMatches, SubCommand}; use console::{style, Emoji}; use indicatif::{ProgressBar, ProgressStyle}; -use solana_clap_utils::{input_parsers::*, input_validators::*, keypair::signer_from_path}; +use solana_clap_utils::{ + commitment::{commitment_arg, COMMITMENT_ARG}, + input_parsers::*, + input_validators::*, + keypair::signer_from_path, +}; use solana_client::{ pubsub_client::{PubsubClient, SlotInfoMessage}, rpc_client::RpcClient, @@ -68,20 +73,13 @@ impl ClusterQuerySubCommands for App<'_, '_> { .validator(is_url) .help("JSON RPC URL for validator, which is useful for validators with a private RPC service") ) - .arg( - Arg::with_name("confirmed") - .long("confirmed") - .takes_value(false) - .help( - "Return information at maximum-lockout commitment level", - ), - ) .arg( Arg::with_name("follow") .long("follow") .takes_value(false) .help("Continue reporting progress even after the validator has caught up"), - ), + ) + .arg(commitment_arg()), ) .subcommand( SubCommand::with_name("cluster-version") @@ -105,14 +103,7 @@ impl ClusterQuerySubCommands for App<'_, '_> { SubCommand::with_name("epoch-info") .about("Get information about the current epoch") .alias("get-epoch-info") - .arg( - Arg::with_name("confirmed") - .long("confirmed") - .takes_value(false) - .help( - "Return information at maximum-lockout commitment level", - ), - ), + .arg(commitment_arg()), ) .subcommand( SubCommand::with_name("genesis-hash") @@ -122,48 +113,20 @@ impl ClusterQuerySubCommands for App<'_, '_> { .subcommand( SubCommand::with_name("slot").about("Get current slot") .alias("get-slot") - .arg( - Arg::with_name("confirmed") - .long("confirmed") - .takes_value(false) - .help( - "Return slot at maximum-lockout commitment level", - ), - ), + .arg(commitment_arg()), ) .subcommand( SubCommand::with_name("epoch").about("Get current epoch") - .arg( - Arg::with_name("confirmed") - .long("confirmed") - .takes_value(false) - .help( - "Return epoch at maximum-lockout commitment level", - ), - ), + .arg(commitment_arg()), ) .subcommand( SubCommand::with_name("total-supply").about("Get total number of SOL") - .arg( - Arg::with_name("confirmed") - .long("confirmed") - .takes_value(false) - .help( - "Return count at maximum-lockout commitment level", - ), - ), + .arg(commitment_arg()), ) .subcommand( SubCommand::with_name("transaction-count").about("Get current transaction count") .alias("get-transaction-count") - .arg( - Arg::with_name("confirmed") - .long("confirmed") - .takes_value(false) - .help( - "Return count at maximum-lockout commitment level", - ), - ), + .arg(commitment_arg()), ) .subcommand( SubCommand::with_name("ping") @@ -204,12 +167,12 @@ impl ClusterQuerySubCommands for App<'_, '_> { .help("Wait up to timeout seconds for transaction confirmation"), ) .arg( - Arg::with_name("confirmed") - .long("confirmed") - .takes_value(false) - .help( - "Wait until the transaction is confirmed at maximum-lockout commitment level", - ), + Arg::with_name(COMMITMENT_ARG.name) + .long(COMMITMENT_ARG.long) + .takes_value(true) + .possible_values(&["default", "max", "recent", "root"]) + .value_name("COMMITMENT_LEVEL") + .help("Wait until the transaction is confirmed at selected commitment level"), ), ) .subcommand( @@ -259,20 +222,13 @@ impl ClusterQuerySubCommands for App<'_, '_> { SubCommand::with_name("validators") .about("Show summary information about the current validators") .alias("show-validators") - .arg( - Arg::with_name("confirmed") - .long("confirmed") - .takes_value(false) - .help( - "Return information at maximum-lockout commitment level", - ), - ) .arg( Arg::with_name("lamports") .long("lamports") .takes_value(false) .help("Display balance in lamports instead of SOL"), - ), + ) + .arg(commitment_arg()), ) .subcommand( SubCommand::with_name("transaction-history") @@ -316,11 +272,8 @@ pub fn parse_catchup( ) -> Result { let node_pubkey = pubkey_of_signer(matches, "node_pubkey", wallet_manager)?.unwrap(); let node_json_rpc_url = value_t!(matches, "node_json_rpc_url", String).ok(); - let commitment_config = if matches.is_present("confirmed") { - CommitmentConfig::default() - } else { - CommitmentConfig::recent() - }; + let commitment_config = + commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent); let follow = matches.is_present("follow"); Ok(CliCommandInfo { command: CliCommand::Catchup { @@ -346,11 +299,8 @@ pub fn parse_cluster_ping( None }; let timeout = Duration::from_secs(value_t_or_exit!(matches, "timeout", u64)); - let commitment_config = if matches.is_present("confirmed") { - CommitmentConfig::default() - } else { - CommitmentConfig::recent() - }; + let commitment_config = + commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent); Ok(CliCommandInfo { command: CliCommand::Ping { lamports, @@ -377,11 +327,8 @@ pub fn parse_get_block_time(matches: &ArgMatches<'_>) -> Result) -> Result { - let commitment_config = if matches.is_present("confirmed") { - CommitmentConfig::default() - } else { - CommitmentConfig::recent() - }; + let commitment_config = + commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent); Ok(CliCommandInfo { command: CliCommand::GetEpochInfo { commitment_config }, signers: vec![], @@ -389,11 +336,8 @@ pub fn parse_get_epoch_info(matches: &ArgMatches<'_>) -> Result) -> Result { - let commitment_config = if matches.is_present("confirmed") { - CommitmentConfig::default() - } else { - CommitmentConfig::recent() - }; + let commitment_config = + commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent); Ok(CliCommandInfo { command: CliCommand::GetSlot { commitment_config }, signers: vec![], @@ -401,11 +345,8 @@ pub fn parse_get_slot(matches: &ArgMatches<'_>) -> Result) -> Result { - let commitment_config = if matches.is_present("confirmed") { - CommitmentConfig::default() - } else { - CommitmentConfig::recent() - }; + let commitment_config = + commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent); Ok(CliCommandInfo { command: CliCommand::GetEpoch { commitment_config }, signers: vec![], @@ -413,11 +354,8 @@ pub fn parse_get_epoch(matches: &ArgMatches<'_>) -> Result) -> Result { - let commitment_config = if matches.is_present("confirmed") { - CommitmentConfig::default() - } else { - CommitmentConfig::recent() - }; + let commitment_config = + commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent); Ok(CliCommandInfo { command: CliCommand::TotalSupply { commitment_config }, signers: vec![], @@ -425,11 +363,8 @@ pub fn parse_total_supply(matches: &ArgMatches<'_>) -> Result) -> Result { - let commitment_config = if matches.is_present("confirmed") { - CommitmentConfig::default() - } else { - CommitmentConfig::recent() - }; + let commitment_config = + commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent); Ok(CliCommandInfo { command: CliCommand::GetTransactionCount { commitment_config }, signers: vec![], @@ -455,11 +390,8 @@ pub fn parse_show_stakes( pub fn parse_show_validators(matches: &ArgMatches<'_>) -> Result { let use_lamports_unit = matches.is_present("lamports"); - let commitment_config = if matches.is_present("confirmed") { - CommitmentConfig::default() - } else { - CommitmentConfig::recent() - }; + let commitment_config = + commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent); Ok(CliCommandInfo { command: CliCommand::ShowValidators { @@ -1396,7 +1328,8 @@ mod tests { "2", "-t", "3", - "--confirmed", + "--commitment", + "max", ]); assert_eq!( parse_command(&test_ping, &default_keypair_file, &mut None).unwrap(), @@ -1406,7 +1339,7 @@ mod tests { interval: Duration::from_secs(1), count: Some(2), timeout: Duration::from_secs(3), - commitment_config: CommitmentConfig::default(), + commitment_config: CommitmentConfig::max(), }, signers: vec![default_keypair.into()], } diff --git a/cli/src/vote.rs b/cli/src/vote.rs index 3dfbd784cca9f1..192b1b06134352 100644 --- a/cli/src/vote.rs +++ b/cli/src/vote.rs @@ -7,7 +7,11 @@ use crate::{ cli_output::{CliEpochVotingHistory, CliLockout, CliVoteAccount}, }; use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand}; -use solana_clap_utils::{input_parsers::*, input_validators::*}; +use solana_clap_utils::{ + commitment::{commitment_arg, COMMITMENT_ARG}, + input_parsers::*, + input_validators::*, +}; use solana_client::rpc_client::RpcClient; use solana_remote_wallet::remote_wallet::RemoteWalletManager; use solana_sdk::{ @@ -160,14 +164,6 @@ impl VoteSubCommands for App<'_, '_> { SubCommand::with_name("vote-account") .about("Show the contents of a vote account") .alias("show-vote-account") - .arg( - Arg::with_name("confirmed") - .long("confirmed") - .takes_value(false) - .help( - "Return information at maximum-lockout commitment level", - ), - ) .arg( pubkey!(Arg::with_name("vote_account_pubkey") .index(1) @@ -180,7 +176,8 @@ impl VoteSubCommands for App<'_, '_> { .long("lamports") .takes_value(false) .help("Display balance in lamports instead of SOL"), - ), + ) + .arg(commitment_arg()), ) .subcommand( SubCommand::with_name("withdraw-from-vote-account") @@ -318,11 +315,8 @@ pub fn parse_vote_get_account_command( let vote_account_pubkey = pubkey_of_signer(matches, "vote_account_pubkey", wallet_manager)?.unwrap(); let use_lamports_unit = matches.is_present("lamports"); - let commitment_config = if matches.is_present("confirmed") { - CommitmentConfig::default() - } else { - CommitmentConfig::recent() - }; + let commitment_config = + commitment_of(matches, COMMITMENT_ARG.long).unwrap_or_else(CommitmentConfig::recent); Ok(CliCommandInfo { command: CliCommand::ShowVoteAccount { pubkey: vote_account_pubkey, diff --git a/core/src/rpc.rs b/core/src/rpc.rs index 1e0c07dae762c5..4b9e466a77b50f 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -87,6 +87,10 @@ impl JsonRpcRequestProcessor { let bank = r_bank_forks.working_bank(); debug!("RPC using working_bank: {:?}", bank.slot()); Ok(bank) + } else if commitment.is_some() && commitment.unwrap().commitment == CommitmentLevel::Root { + let slot = r_bank_forks.root(); + debug!("RPC using node root: {:?}", slot); + Ok(r_bank_forks.get(slot).cloned().unwrap()) } else { let cluster_root = self .block_commitment_cache @@ -169,9 +173,7 @@ impl JsonRpcRequestProcessor { pub fn get_epoch_schedule(&self) -> Result { // Since epoch schedule data comes from the genesis config, any commitment level should be // fine - Ok(*self - .bank(Some(CommitmentConfig::recent()))? - .epoch_schedule()) + Ok(*self.bank(Some(CommitmentConfig::root()))?.epoch_schedule()) } pub fn get_balance( diff --git a/docs/src/apps/jsonrpc-api.md b/docs/src/apps/jsonrpc-api.md index bfe62e80e236f2..b1ffc522883a31 100644 --- a/docs/src/apps/jsonrpc-api.md +++ b/docs/src/apps/jsonrpc-api.md @@ -95,7 +95,8 @@ Requests can be sent in batches by sending an array of JSON-RPC request objects Solana nodes choose which bank state to query based on a commitment requirement set by the client. Clients may specify either: -* `{"commitment":"max"}` - the node will query the most recent bank having reached `MAX_LOCKOUT_HISTORY` confirmations +* `{"commitment":"max"}` - the node will query the most recent bank confirmed by the cluster as having reached `MAX_LOCKOUT_HISTORY` confirmations +* `{"commitment":"root"}` - the node will query the most recent bank having reached `MAX_LOCKOUT_HISTORY` confirmations on this node * `{"commitment":"recent"}` - the node will query its most recent bank state The commitment parameter should be included as the last element in the `params` array: @@ -196,7 +197,7 @@ The result field will be a JSON object containing: * `commitment` - commitment, comprising either: * `` - Unknown block - * `` - commitment, array of u64 integers logging the amount of cluster stake in lamports that has voted on the block at each depth from 0 to `MAX_LOCKOUT_HISTORY` + * `` - commitment, array of u64 integers logging the amount of cluster stake in lamports that has voted on the block at each depth from 0 to `MAX_LOCKOUT_HISTORY` + 1 * `totalStake` - total active stake, in lamports, of the current epoch #### Example: @@ -206,7 +207,7 @@ The result field will be a JSON object containing: curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getBlockCommitment","params":[5]}' http://localhost:8899 // Result -{"jsonrpc":"2.0","result":{"commitment":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,32],"totalStake": 42},"id":1} +{"jsonrpc":"2.0","result":{"commitment":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,32],"totalStake": 42},"id":1} ``` ### getBlockTime diff --git a/sdk/src/commitment_config.rs b/sdk/src/commitment_config.rs index aa6f9ee4b24829..24ba5f7ebd49a9 100644 --- a/sdk/src/commitment_config.rs +++ b/sdk/src/commitment_config.rs @@ -25,6 +25,12 @@ impl CommitmentConfig { } } + pub fn root() -> Self { + Self { + commitment: CommitmentLevel::Root, + } + } + pub fn ok(self) -> Option { if self == Self::default() { None @@ -39,4 +45,5 @@ impl CommitmentConfig { pub enum CommitmentLevel { Max, Recent, + Root, }