diff --git a/CHANGELOG.md b/CHANGELOG.md index 90a61fe045..9148bcb560 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -173,6 +173,12 @@ and this project adheres to - cosmwasm-std: Remove `StakingMsg::Withdraw` in favour of `DistributionMsg::SetWithdrawAddress` and `DistributionMsg::WithdrawDelegatorReward` ([#848]). +- cosmwasm-std: Rename `StakingQuery::Validators`, `ValidatorsResponse` and + `QuerierWrapper::query_validators` to `StakingQuery::AllValidators`, + `AllValidatorsResponse` and `QuerierWrapper.query_all_validators`. Add + `StakingQuery::Validator`, `ValidatorResponse` and + `QuerierWrapper::query_validator` to allow querying a single validator. + ([#879]) [#696]: https://github.com/CosmWasm/cosmwasm/issues/696 [#697]: https://github.com/CosmWasm/cosmwasm/issues/697 @@ -186,6 +192,7 @@ and this project adheres to [#871]: https://github.com/CosmWasm/cosmwasm/issues/871 [#861]: https://github.com/CosmWasm/cosmwasm/issues/861 [#848]: https://github.com/CosmWasm/cosmwasm/issues/848 +[#879]: https://github.com/CosmWasm/cosmwasm/pull/879 ### Deprecated diff --git a/contracts/reflect/schema/query_msg.json b/contracts/reflect/schema/query_msg.json index 8b24046d67..9219db7ae3 100644 --- a/contracts/reflect/schema/query_msg.json +++ b/contracts/reflect/schema/query_msg.json @@ -420,17 +420,39 @@ "additionalProperties": false }, { - "description": "Returns all registered Validators on the system", + "description": "Returns all validators in the currently active validator set.\n\nThe query response type is `AllValidatorsResponse`.", "type": "object", "required": [ - "validators" + "all_validators" ], "properties": { - "validators": { + "all_validators": { "type": "object" } }, "additionalProperties": false + }, + { + "description": "Returns the validator at the given address. Returns None if the validator is not part of the currently active validator set.\n\nThe query response type is `ValidatorResponse`.", + "type": "object", + "required": [ + "validator" + ], + "properties": { + "validator": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "description": "The validator's address (e.g. (e.g. cosmosvaloper1...))", + "type": "string" + } + } + } + }, + "additionalProperties": false } ] }, diff --git a/contracts/staking/src/contract.rs b/contracts/staking/src/contract.rs index 6641bc2181..44224438af 100644 --- a/contracts/staking/src/contract.rs +++ b/contracts/staking/src/contract.rs @@ -24,8 +24,8 @@ pub fn instantiate( msg: InstantiateMsg, ) -> StdResult { // ensure the validator is registered - let vals = deps.querier.query_validators()?; - if !vals.iter().any(|v| v.address == msg.validator) { + let validator = deps.querier.query_validator(msg.validator.clone())?; + if validator.is_none() { return Err(StdError::generic_err(format!( "{} is not in the current validator set", msg.validator diff --git a/packages/std/src/lib.rs b/packages/std/src/lib.rs index 9a2fffaf0c..54560717b0 100644 --- a/packages/std/src/lib.rs +++ b/packages/std/src/lib.rs @@ -46,8 +46,8 @@ pub use crate::query::{ }; #[cfg(feature = "staking")] pub use crate::query::{ - AllDelegationsResponse, BondedDenomResponse, Delegation, FullDelegation, StakingQuery, - Validator, ValidatorsResponse, + AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, Delegation, FullDelegation, + StakingQuery, Validator, ValidatorResponse, }; pub use crate::results::{ attr, wasm_execute, wasm_instantiate, Attribute, BankMsg, ContractResult, CosmosMsg, Empty, diff --git a/packages/std/src/mock.rs b/packages/std/src/mock.rs index f3359338cc..6e926edd0f 100644 --- a/packages/std/src/mock.rs +++ b/packages/std/src/mock.rs @@ -15,8 +15,8 @@ use crate::query::{ }; #[cfg(feature = "staking")] use crate::query::{ - AllDelegationsResponse, BondedDenomResponse, DelegationResponse, FullDelegation, StakingQuery, - Validator, ValidatorsResponse, + AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, DelegationResponse, + FullDelegation, StakingQuery, Validator, ValidatorResponse, }; use crate::results::{ContractResult, Empty, SystemResult}; use crate::serde::{from_slice, to_binary}; @@ -459,12 +459,21 @@ impl StakingQuerier { }; to_binary(&res).into() } - StakingQuery::Validators {} => { - let res = ValidatorsResponse { + StakingQuery::AllValidators {} => { + let res = AllValidatorsResponse { validators: self.validators.clone(), }; to_binary(&res).into() } + StakingQuery::Validator { address } => { + let validator: Option = self + .validators + .iter() + .find(|validator| validator.address == *address) + .cloned(); + let res = ValidatorResponse { validator }; + to_binary(&res).into() + } StakingQuery::AllDelegations { delegator } => { let delegations: Vec<_> = self .delegations @@ -874,7 +883,7 @@ mod tests { #[cfg(feature = "staking")] #[test] - fn staking_querier_validators() { + fn staking_querier_all_validators() { let val1 = Validator { address: String::from("validator-one"), commission: Decimal::percent(1), @@ -892,13 +901,62 @@ mod tests { // one match let raw = staking - .query(&StakingQuery::Validators {}) + .query(&StakingQuery::AllValidators {}) .unwrap() .unwrap(); - let vals: ValidatorsResponse = from_binary(&raw).unwrap(); + let vals: AllValidatorsResponse = from_binary(&raw).unwrap(); assert_eq!(vals.validators, vec![val1, val2]); } + #[cfg(feature = "staking")] + #[test] + fn staking_querier_validator() { + let address1 = String::from("validator-one"); + let address2 = String::from("validator-two"); + let address_non_existent = String::from("wannabe-validator"); + + let val1 = Validator { + address: address1.clone(), + commission: Decimal::percent(1), + max_commission: Decimal::percent(3), + max_change_rate: Decimal::percent(1), + }; + let val2 = Validator { + address: address2.clone(), + commission: Decimal::permille(15), + max_commission: Decimal::permille(40), + max_change_rate: Decimal::permille(5), + }; + + let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]); + + // query 1 + let raw = staking + .query(&StakingQuery::Validator { address: address1 }) + .unwrap() + .unwrap(); + let res: ValidatorResponse = from_binary(&raw).unwrap(); + assert_eq!(res.validator, Some(val1)); + + // query 2 + let raw = staking + .query(&StakingQuery::Validator { address: address2 }) + .unwrap() + .unwrap(); + let res: ValidatorResponse = from_binary(&raw).unwrap(); + assert_eq!(res.validator, Some(val2)); + + // query non-existent + let raw = staking + .query(&StakingQuery::Validator { + address: address_non_existent, + }) + .unwrap() + .unwrap(); + let res: ValidatorResponse = from_binary(&raw).unwrap(); + assert_eq!(res.validator, None); + } + #[cfg(feature = "staking")] // gets delegators from query or panic fn get_all_delegators>( diff --git a/packages/std/src/query/mod.rs b/packages/std/src/query/mod.rs index dc66dd0c37..fef9a0d1f2 100644 --- a/packages/std/src/query/mod.rs +++ b/packages/std/src/query/mod.rs @@ -15,8 +15,8 @@ mod wasm; pub use bank::{AllBalanceResponse, BalanceResponse, BankQuery}; #[cfg(feature = "staking")] pub use staking::{ - AllDelegationsResponse, BondedDenomResponse, Delegation, DelegationResponse, FullDelegation, - StakingQuery, Validator, ValidatorsResponse, + AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, Delegation, + DelegationResponse, FullDelegation, StakingQuery, Validator, ValidatorResponse, }; #[cfg(feature = "stargate")] pub use stargate::StargateResponse; diff --git a/packages/std/src/query/staking.rs b/packages/std/src/query/staking.rs index b28fb696d1..0300e1e946 100644 --- a/packages/std/src/query/staking.rs +++ b/packages/std/src/query/staking.rs @@ -19,8 +19,18 @@ pub enum StakingQuery { delegator: String, validator: String, }, - /// Returns all registered Validators on the system - Validators {}, + /// Returns all validators in the currently active validator set. + /// + /// The query response type is `AllValidatorsResponse`. + AllValidators {}, + /// Returns the validator at the given address. Returns None if the validator is + /// not part of the currently active validator set. + /// + /// The query response type is `ValidatorResponse`. + Validator { + /// The validator's address (e.g. (e.g. cosmosvaloper1...)) + address: String, + }, } /// BondedDenomResponse is data format returned from StakingRequest::BondedDenom query @@ -85,12 +95,18 @@ pub struct FullDelegation { pub accumulated_rewards: Vec, } -/// ValidatorsResponse is data format returned from StakingRequest::Validators query +/// The data format returned from StakingRequest::AllValidators query #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct ValidatorsResponse { +pub struct AllValidatorsResponse { pub validators: Vec, } +/// The data format returned from StakingRequest::Validator query +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct ValidatorResponse { + pub validator: Option, +} + /// Instances are created in the querier. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct Validator { diff --git a/packages/std/src/traits.rs b/packages/std/src/traits.rs index 52718b4a27..d2b752f973 100644 --- a/packages/std/src/traits.rs +++ b/packages/std/src/traits.rs @@ -12,8 +12,8 @@ use crate::query::{ }; #[cfg(feature = "staking")] use crate::query::{ - AllDelegationsResponse, BondedDenomResponse, Delegation, DelegationResponse, FullDelegation, - StakingQuery, Validator, ValidatorsResponse, + AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, Delegation, + DelegationResponse, FullDelegation, StakingQuery, Validator, ValidatorResponse, }; use crate::results::{ContractResult, Empty, SystemResult}; use crate::serde::{from_binary, to_binary, to_vec}; @@ -261,12 +261,22 @@ impl<'a> QuerierWrapper<'a> { } #[cfg(feature = "staking")] - pub fn query_validators(&self) -> StdResult> { - let request = StakingQuery::Validators {}.into(); - let res: ValidatorsResponse = self.query(&request)?; + pub fn query_all_validators(&self) -> StdResult> { + let request = StakingQuery::AllValidators {}.into(); + let res: AllValidatorsResponse = self.query(&request)?; Ok(res.validators) } + #[cfg(feature = "staking")] + pub fn query_validator>(&self, address: U) -> StdResult> { + let request = StakingQuery::Validator { + address: address.into(), + } + .into(); + let res: ValidatorResponse = self.query(&request)?; + Ok(res.validator) + } + #[cfg(feature = "staking")] pub fn query_bonded_denom(&self) -> StdResult { let request = StakingQuery::BondedDenom {}.into();