Skip to content

Commit

Permalink
Merge pull request #92 from confio/87-valset-add-jailed-validators-query
Browse files Browse the repository at this point in the history
Valset: Implement ListJailedValidators query
  • Loading branch information
ueco-jb committed Feb 9, 2022
2 parents 58bc19f + e9e5ec4 commit 73aea68
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 0 deletions.
46 changes: 46 additions & 0 deletions contracts/tgrade-valset/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,12 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result<Binary, ContractErro
start_after,
limit,
)?)?),
ListJailedValidators { start_after, limit } => Ok(to_binary(&list_jailed_validators(
deps,
env,
start_after,
limit,
)?)?),
SimulateActiveValidators {} => Ok(to_binary(&simulate_active_validators(deps, env)?)?),
ListValidatorSlashing { operator } => {
Ok(to_binary(&list_validator_slashing(deps, env, operator)?)?)
Expand Down Expand Up @@ -526,6 +532,46 @@ fn list_active_validators(
})
}

fn list_jailed_validators(
deps: Deps,
env: Env,
start_after: Option<String>,
limit: Option<u32>,
) -> Result<ListValidatorResponse, ContractError> {
let cfg = CONFIG.load(deps.storage)?;
let limit = limit.unwrap_or(DEFAULT_LIMIT).min(MAX_LIMIT) as usize;
let start_after = maybe_addr(deps.api, start_after)?;
let start = start_after.map(|addr| Bound::exclusive(addr.as_str()));

let validators = JAIL
.range(deps.storage, start, None, Order::Ascending)
.map(|jail| {
let (addr, jailing_period) = jail?;
if !(cfg.auto_unjail && jailing_period.is_expired(&env.block)) {
Ok(Some((addr, jailing_period)))
} else {
Ok(None)
}
})
.collect::<Result<Vec<Option<_>>, ContractError>>()?
.into_iter()
.flatten()
.map(|(addr, jailing_period)| {
let info = operators().load(deps.storage, &Addr::unchecked(&addr))?;
Ok(OperatorResponse {
operator: addr.into(),
metadata: info.metadata,
pubkey: info.pubkey.into(),
jailed_until: Some(jailing_period),
active_validator: info.active_validator,
})
})
.take(limit)
.collect::<Result<Vec<OperatorResponse>, ContractError>>()?;

Ok(ListValidatorResponse { validators })
}

fn simulate_active_validators(
deps: Deps,
env: Env,
Expand Down
6 changes: 6 additions & 0 deletions contracts/tgrade-valset/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ pub enum QueryMsg {
limit: Option<u32>,
},

/// Returns ListValidatorsResponse
ListJailedValidators {
start_after: Option<String>,
limit: Option<u32>,
},

/// This will calculate who the new validators would be if
/// we recalculated end block right now.
/// Also returns ListActiveValidatorsResponse
Expand Down
62 changes: 62 additions & 0 deletions contracts/tgrade-valset/src/multitest/jailing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,3 +348,65 @@ fn jailed_validators_show_up_as_inactive_when_listed() {
assert!(operators[2].active_validator);
assert!(operators[3].active_validator);
}

#[test]
fn list_jailed_validators_all() {
let members = vec!["member1", "member2", "member3", "member4"];
let mut suite = SuiteBuilder::new()
.with_engagement(&members_init(&members, &[2, 3, 5, 8]))
.with_operators(&members)
.build();
let admin = suite.admin().to_owned();

// Jailing operators as test prerequirements
suite.jail(&admin, members[0], Duration::new(3600)).unwrap();
suite.jail(&admin, members[2], Duration::new(7200)).unwrap();

let operators = suite.list_jailed_validators(None, None).unwrap();
assert_eq!(operators.len(), 2);
assert_eq!(operators[0].operator, members[0]);
assert_eq!(operators[1].operator, members[2]);

// Moving forward so jailing periods expired
suite.advance_seconds(4000).unwrap();

// Unjail one of the jailed ops
suite.unjail(&admin, members[0]).unwrap();

let operators = suite.list_jailed_validators(None, None).unwrap();
assert_eq!(operators.len(), 1);
assert_eq!(operators[0].operator, members[2]);
}

#[test]
fn list_jailed_validators_with_pagination() {
let members = vec!["member1", "member2", "member3", "member4", "member5"];
let mut suite = SuiteBuilder::new()
.with_engagement(&members_init(&members, &[2, 3, 5, 8, 10]))
.with_operators(&members)
.build();
let admin = suite.admin().to_owned();

// Jailing operators as test prerequirements
suite.jail(&admin, members[0], Duration::new(3600)).unwrap();
suite.jail(&admin, members[1], Duration::new(3600)).unwrap();
suite.jail(&admin, members[2], Duration::new(7200)).unwrap();
suite.jail(&admin, members[3], Duration::new(7200)).unwrap();
suite.jail(&admin, members[4], Duration::new(7200)).unwrap();

let operators = suite.list_jailed_validators(None, None).unwrap();
assert_eq!(operators.len(), 5);

let operators = suite.list_jailed_validators(None, 3).unwrap();
assert_eq!(operators.len(), 3);
assert_eq!(operators[0].operator, members[0]);
assert_eq!(operators[1].operator, members[1]);
assert_eq!(operators[2].operator, members[2]);

let operators = suite
.list_jailed_validators(operators.last().unwrap().operator.clone(), None)
.unwrap();
assert_eq!(operators.len(), 2);
assert_eq!(operators[0].operator, members[3]);
assert_eq!(operators[1].operator, members[4]);
}
16 changes: 16 additions & 0 deletions contracts/tgrade-valset/src/multitest/suite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,22 @@ impl Suite {
Ok(resp.validators)
}

pub fn list_jailed_validators(
&self,
start_after: impl Into<Option<String>>,
limit: impl Into<Option<u32>>,
) -> StdResult<Vec<OperatorResponse>> {
let resp: ListValidatorResponse = self.app.wrap().query_wasm_smart(
self.valset.clone(),
&QueryMsg::ListJailedValidators {
start_after: start_after.into(),
limit: limit.into(),
},
)?;

Ok(resp.validators)
}

pub fn list_validator_slashing(&self, addr: &str) -> StdResult<ListValidatorSlashingResponse> {
let resp = self.app.wrap().query_wasm_smart(
self.valset.clone(),
Expand Down

0 comments on commit 73aea68

Please sign in to comment.