Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Commit

Permalink
v1.16: Hide Keybase and replace with URL (backport of #31852) (#31984)
Browse files Browse the repository at this point in the history
Hide Keybase and replace with URL (#31852)

(cherry picked from commit 2f4a189)

Co-authored-by: Michael <[email protected]>
  • Loading branch information
mergify[bot] and michaelh-laine authored Jun 6, 2023
1 parent ca2881a commit 7bfe386
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 31 deletions.
2 changes: 1 addition & 1 deletion account-decoder/src/validator_info.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use solana_config_program::ConfigState;

pub const MAX_SHORT_FIELD_LENGTH: usize = 70;
pub const MAX_SHORT_FIELD_LENGTH: usize = 80;
pub const MAX_LONG_FIELD_LENGTH: usize = 300;
pub const MAX_VALIDATOR_INFO: u64 = 576;

Expand Down
54 changes: 46 additions & 8 deletions cli/src/validator_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use {
cli::{CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult},
spend_utils::{resolve_spend_tx_and_check_account_balance, SpendAmount},
},
bincode::deserialize,
bincode::{deserialize, serialized_size},
clap::{App, AppSettings, Arg, ArgMatches, SubCommand},
reqwest::blocking::Client,
serde_json::{Map, Value},
Expand Down Expand Up @@ -41,6 +41,19 @@ pub fn check_details_length(string: String) -> Result<(), String> {
}
}

pub fn check_total_length(info: &ValidatorInfo) -> Result<(), String> {
let size = serialized_size(&info).unwrap();
let limit = ValidatorInfo::max_space();

if size > limit {
Err(format!(
"Total size {size:?} exceeds limit of {limit:?} bytes"
))
} else {
Ok(())
}
}

// Return an error if url field is too long or cannot be parsed.
pub fn check_url(string: String) -> Result<(), String> {
is_url(string.clone())?;
Expand Down Expand Up @@ -91,6 +104,10 @@ fn parse_args(matches: &ArgMatches<'_>) -> Value {
if let Some(url) = matches.value_of("website") {
map.insert("website".to_string(), Value::String(url.to_string()));
}

if let Some(icon_url) = matches.value_of("icon_url") {
map.insert("iconUrl".to_string(), Value::String(icon_url.to_string()));
}
if let Some(details) = matches.value_of("details") {
map.insert("details".to_string(), Value::String(details.to_string()));
}
Expand Down Expand Up @@ -161,13 +178,23 @@ impl ValidatorInfoSubCommands for App<'_, '_> {
.validator(check_url)
.help("Validator website url"),
)
.arg(
Arg::with_name("icon_url")
.short("i")
.long("icon-url")
.value_name("URL")
.takes_value(true)
.validator(check_url)
.help("Validator icon URL"),
)
.arg(
Arg::with_name("keybase_username")
.short("n")
.long("keybase")
.value_name("USERNAME")
.takes_value(true)
.validator(is_short_field)
.hidden(hidden_unless_forced()) // Being phased out
.help("Validator Keybase username"),
)
.arg(
Expand Down Expand Up @@ -240,11 +267,11 @@ pub fn process_set_validator_info(
) -> ProcessResult {
// Validate keybase username
if let Some(string) = validator_info.get("keybaseUsername") {
let result = verify_keybase(&config.signers[0].pubkey(), string);
if result.is_err() {
if force_keybase {
println!("--force supplied, ignoring: {result:?}");
} else {
if force_keybase {
println!("--force supplied, skipping Keybase verification");
} else {
let result = verify_keybase(&config.signers[0].pubkey(), string);
if result.is_err() {
result.map_err(|err| {
CliError::BadParameter(format!("Invalid validator keybase username: {err}"))
})?;
Expand All @@ -255,6 +282,14 @@ pub fn process_set_validator_info(
let validator_info = ValidatorInfo {
info: validator_string,
};

let result = check_total_length(&validator_info);
if result.is_err() {
result.map_err(|err| {
CliError::BadParameter(format!("Maximum size for validator info: {err}"))
})?;
}

// Check for existing validator-info account
let all_config = rpc_client.get_program_accounts(&solana_config_program::id())?;
let existing_account = all_config
Expand Down Expand Up @@ -426,7 +461,7 @@ mod tests {
fn test_check_url() {
let url = "http://test.com";
assert_eq!(check_url(url.to_string()), Ok(()));
let long_url = "http://7cLvFwLCbyHuXQ1RGzhCMobAWYPMSZ3VbUml1qWi1nkc3FD7zj9hzTZzMvYJ.com";
let long_url = "http://7cLvFwLCbyHuXQ1RGzhCMobAWYPMSZ3VbUml1CMobAWYPMSZ3VbUml1qWi1nkc3FD7zj9hzTZzMvYJ.com";
assert!(check_url(long_url.to_string()).is_err());
let non_url = "not parseable";
assert!(check_url(non_url.to_string()).is_err());
Expand All @@ -436,7 +471,7 @@ mod tests {
fn test_is_short_field() {
let name = "Alice Validator";
assert_eq!(is_short_field(name.to_string()), Ok(()));
let long_name = "Alice 7cLvFwLCbyHuXQ1RGzhCMobAWYPMSZ3VbUml1qWi1nkc3FD7zj9hzTZzMvYJt6rY9";
let long_name = "Alice 7cLvFwLCbyHuXQ1RGzhCMobAWYPMSZ3VbUml1qWi1nkc3FD7zj9hzTZzMvYJt6rY9j9hzTZzMvYJt6rY9";
assert!(is_short_field(long_name.to_string()).is_err());
}

Expand All @@ -460,6 +495,8 @@ mod tests {
"Alice",
"-n",
"alice_keybase",
"-i",
"https://test.com/icon.png",
]);
let subcommand_matches = matches.subcommand();
assert_eq!(subcommand_matches.0, "validator-info");
Expand All @@ -471,6 +508,7 @@ mod tests {
let expected = json!({
"name": "Alice",
"keybaseUsername": "alice_keybase",
"iconUrl": "https://test.com/icon.png",
});
assert_eq!(parse_args(matches), expected);
}
Expand Down
29 changes: 7 additions & 22 deletions docs/src/running-validator/validator-info.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ For details about optional fields for VALIDATOR_INFO_ARGS:
solana validator-info publish --help
```

The recommended dimensions for the validator icon are 360x360px and PNG format.

## Example Commands

Example publish command:

```bash
solana validator-info publish "Elvis Validator" -n elvis -w "https://elvis-validates.com"
solana validator-info publish "Elvis Validator" -w "https://elvis-validates.com" -i "https://elvis-validates.com/my-icon.png"
```

Example query command:
Expand All @@ -37,28 +39,11 @@ which outputs
```text
Validator info from 8WdJvDz6obhADdxpGCiJKZsDYwTLNEDFizayqziDc9ah
Validator pubkey: 6dMH3u76qZ7XG4bVboVRnBHR2FfrxEqTTTyj4xmyDMWo
Info: {"keybaseUsername":"elvis","name":"Elvis Validator","website":"https://elvis-validates.com"}
Info: {"iconUrl":"elvis","name":"Elvis Validator","website":"https://elvis-validates.com"}
```

## Keybase

Including a Keybase username allows client applications \(like the Solana
Network Explorer\) to automatically pull in your validator public profile,
including cryptographic proofs, brand identity, etc. To connect your validator
pubkey with Keybase:

1. Join [https://keybase.io/](https://keybase.io/) and complete the profile for your validator
2. Add your validator **identity pubkey** to Keybase:

- Create an empty file on your local computer called `validator-<PUBKEY>`
- In Keybase, navigate to the Files section, and upload your pubkey file to
For older accounts instead of `iconUrl` you might see `keybaseUsername` as those accounts used Keybase for their validator icon (see next section for further information).

a `solana` subdirectory in your public folder: `/keybase/public/<KEYBASE_USERNAME>/solana`

- To check your pubkey, ensure you can successfully browse to

`https://keybase.pub/<KEYBASE_USERNAME>/solana/validator-<PUBKEY>`

3. Add or update your `solana validator-info` with your Keybase username. The
## Keybase

CLI will verify the `validator-<PUBKEY>` file
Previously Keybase was used by validators to provide their validator icon, however Keybase has sunset its service and thus is no longer supported. Some old validator info accounts will still contain keybase usernames this is reflected in the serialized data returend when querying these validator info accounts.

0 comments on commit 7bfe386

Please sign in to comment.