Skip to content
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

Delete pending validators #94

Merged
merged 5 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ members = ["crates/ash_cli", "crates/ash_sdk"]
resolver = "2"

[workspace.package]
version = "0.4.2"
version = "0.4.3-rc.1"
edition = "2021"
authors = ["E36 Knots"]
homepage = "https://ash.center"
Expand Down
2 changes: 1 addition & 1 deletion crates/ash_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ categories.workspace = true
keywords.workspace = true

[dependencies]
ash_sdk = { path = "../ash_sdk", version = "0.4.2" }
ash_sdk = { path = "../ash_sdk", version = "0.4.3-rc.1" }
clap = { version = "4.0.32", features = ["derive", "env", "cargo", "string"] }
colored = "2.0.0"
exitcode = "1.1.2"
Expand Down
11 changes: 0 additions & 11 deletions crates/ash_cli/src/avalanche.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,6 @@ fn update_subnet_validators(
Ok(())
}

// Update a Subnet's pending validators
fn update_subnet_pending_validators(
network: &mut AvalancheNetwork,
subnet_id: &str,
) -> Result<(), CliError> {
network
.update_subnet_pending_validators(parse_id(subnet_id)?)
.map_err(|e| CliError::dataerr(format!("Error updating pending validators: {e}")))?;
Ok(())
}

// Parse avalanche subcommand
pub(crate) fn parse(
avalanche: AvalancheCommand,
Expand Down
1 change: 0 additions & 1 deletion crates/ash_cli/src/avalanche/subnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ fn info(
let mut network = load_network(network_name, config)?;
update_network_subnets(&mut network)?;
update_subnet_validators(&mut network, id)?;
update_subnet_pending_validators(&mut network, id)?;

let subnet = network
.get_subnet(parse_id(id)?)
Expand Down
59 changes: 13 additions & 46 deletions crates/ash_cli/src/avalanche/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,7 @@ enum ValidatorSubcommands {
},
/// List the Subnet's validators
#[command(version = version_tx_cmd(false))]
List {
/// List pending validators
#[arg(long, short = 'p')]
pending: bool,
},
List,
/// Show validator information
#[command(version = version_tx_cmd(false))]
Info {
Expand All @@ -106,48 +102,28 @@ enum ValidatorSubcommands {
fn list(
network_name: &str,
subnet_id: &str,
pending: bool,
config: Option<&str>,
json: bool,
) -> Result<(), CliError> {
let mut network = load_network(network_name, config)?;
update_network_subnets(&mut network)?;
let subnet;
let validators;

let first_line = match pending {
true => {
update_subnet_pending_validators(&mut network, subnet_id)?;
subnet = network
.get_subnet(parse_id(subnet_id)?)
.map_err(|e| CliError::dataerr(format!("Error listing validators: {e}")))?;
validators = subnet.pending_validators.clone();
format!(
"Found {} pending validators on Subnet '{}':",
type_colorize(&subnet.pending_validators.len()),
type_colorize(&subnet_id)
)
}
false => {
update_subnet_validators(&mut network, subnet_id)?;
subnet = network
.get_subnet(parse_id(subnet_id)?)
.map_err(|e| CliError::dataerr(format!("Error listing validators: {e}")))?;
validators = subnet.validators.clone();
format!(
"Found {} validators on Subnet '{}':",
type_colorize(&subnet.validators.len()),
type_colorize(&subnet_id)
)
}
};
update_subnet_validators(&mut network, subnet_id)?;
let subnet = network
.get_subnet(parse_id(subnet_id)?)
.map_err(|e| CliError::dataerr(format!("Error listing validators: {e}")))?;
let validators = subnet.validators.clone();
format!(
"Found {} validators on Subnet '{}':",
type_colorize(&subnet.validators.len()),
type_colorize(&subnet_id)
);

if json {
println!("{}", serde_json::to_string(&validators).unwrap());
return Ok(());
}

println!("{}", first_line);
for validator in validators.iter() {
println!(
"{}",
Expand Down Expand Up @@ -256,10 +232,7 @@ fn add(
start_time_parsed,
end_time_parsed,
delegation_fee,
match signer {
Some(_) => Some(signer_parsed),
None => None,
},
signer.map(|_| signer_parsed),
wait,
)
.await
Expand Down Expand Up @@ -331,12 +304,6 @@ pub(crate) fn parse(
ValidatorSubcommands::Info { id } => {
info(&validator.network, &validator.subnet_id, &id, config, json)
}
ValidatorSubcommands::List { pending } => list(
&validator.network,
&validator.subnet_id,
pending,
config,
json,
),
ValidatorSubcommands::List => list(&validator.network, &validator.subnet_id, config, json),
}
}
5 changes: 2 additions & 3 deletions crates/ash_cli/src/utils/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ use std::str::FromStr;
// Parse an ID from a string
pub(crate) fn parse_id(id: &str) -> Result<Id, CliError> {
// Try to parse the ID as CB58 first
let id_from_cb58 = Id::from_str(id);
if id_from_cb58.is_ok() {
return Ok(id_from_cb58.unwrap());
if let Ok(id) = Id::from_str(id) {
return Ok(id);
}

// Then try to parse it as hex
Expand Down
28 changes: 0 additions & 28 deletions crates/ash_sdk/src/avalanche.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,34 +295,6 @@ impl AvalancheNetwork {
Ok(())
}

/// Update the pending validators of a Subnet by querying an API endpoint
pub fn update_subnet_pending_validators(&mut self, subnet_id: Id) -> Result<(), AshError> {
let rpc_url = &self.get_pchain()?.rpc_url;

let validators = platformvm::get_pending_validators(rpc_url, subnet_id)?;

// Replace the pending validators of the Subnet
let mut subnet = self.get_subnet(subnet_id)?.clone();

subnet.pending_validators = validators;

// Get the index of the Subnet
let subnet_index = self
.subnets
.iter()
.position(|subnet| subnet.id == subnet_id)
.ok_or(AvalancheNetworkError::NotFound {
network: self.name.clone(),
target_type: "Subnet".to_string(),
target_value: subnet_id.to_string(),
})?;

// Replace the Subnet
self.subnets[subnet_index] = subnet;

Ok(())
}

/// Check if the operation is allowed on the network
/// If not, return an error
fn check_operation_allowed(
Expand Down
46 changes: 2 additions & 44 deletions crates/ash_sdk/src/avalanche/jsonrpc/platformvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use crate::avalanche::{
blockchains::AvalancheBlockchain,
jsonrpc::{get_json_rpc_req_result, JsonRpcResponse},
subnets::{AvalancheSubnet, AvalancheSubnetDelegator, AvalancheSubnetValidator},
subnets::{AvalancheSubnet, AvalancheSubnetValidator},
};
use crate::{errors::*, impl_json_rpc_response};
use avalanche_types::{
Expand Down Expand Up @@ -51,7 +51,6 @@ impl_json_rpc_response!(
);
impl_json_rpc_response!(GetBlockchainsResponse, GetBlockchainsResult);
impl_json_rpc_response!(GetCurrentValidatorsResponse, GetCurrentValidatorsResult);
impl_json_rpc_response!(GetPendingValidatorsResponse, GetPendingValidatorsResult);

/// Get the Subnets of the network by querying the P-Chain API
pub fn get_network_subnets(
Expand Down Expand Up @@ -124,47 +123,6 @@ pub fn get_current_validators(
Ok(current_validators)
}

/// Get the pending validators of a Subnet by querying the P-Chain API
pub fn get_pending_validators(
rpc_url: &str,
subnet_id: Id,
) -> Result<Vec<AvalancheSubnetValidator>, RpcError> {
let pending_validators_result: GetPendingValidatorsResult =
get_json_rpc_req_result::<GetPendingValidatorsResponse, GetPendingValidatorsResult>(
rpc_url,
"platform.getPendingValidators",
Some(ureq::json!({ "subnetID": subnet_id.to_string() })),
)?;

let mut pending_validators: Vec<AvalancheSubnetValidator> = pending_validators_result
.validators
.iter()
.map(|validator| AvalancheSubnetValidator::from_api_primary_validator(validator, subnet_id))
.collect();
let pending_validators_iter = pending_validators.clone();

// For each pending validator, add related delegators
for pending_validator in pending_validators_iter.iter() {
let delegators: Vec<AvalancheSubnetDelegator> = pending_validators_result
.delegators
.iter()
.filter(|delegator| delegator.node_id == pending_validator.node_id)
.cloned()
.map(Into::into)
.collect();

if !delegators.is_empty() {
pending_validators
.iter_mut()
.find(|validator| validator.node_id == pending_validator.node_id)
.unwrap()
.delegators = Some(delegators);
}
}

Ok(pending_validators)
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -176,7 +134,7 @@ mod tests {
const AVAX_FUJI_CCHAIN_ID: &str = "yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp";
const AVAX_FUJI_XCHAIN_ID: &str = "2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm";
// ID of a node operated by Ava Labs
const AVAX_FUJI_NODE_ID: &str = "NodeID-4B4rc5vdD1758JSBYL1xyvE5NHGzz6xzH";
const AVAX_FUJI_NODE_ID: &str = "NodeID-4KXitMCoE9p2BHA6VzXtaTxLoEjNDo2Pt";

// Load the test network from the ASH_TEST_CONFIG file
fn load_test_network() -> AvalancheNetwork {
Expand Down
Loading