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

Valset: Implement ListJailedValidators query #92

Merged
merged 4 commits into from
Feb 9, 2022
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
46 changes: 46 additions & 0 deletions contracts/tgrade-valset/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,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 @@ -523,6 +529,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 @@ -293,6 +293,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 @@ -690,6 +690,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