Skip to content

Commit

Permalink
valset: optimize marking operators as active val
Browse files Browse the repository at this point in the history
  • Loading branch information
uint committed Jan 26, 2022
1 parent 6a5a5ff commit e0f4667
Showing 1 changed file with 80 additions and 81 deletions.
161 changes: 80 additions & 81 deletions contracts/tgrade-valset/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,19 +538,6 @@ fn end_block(deps: DepsMut, env: Env) -> Result<Response, ContractError> {
// calculate and store new validator set
let (validators, auto_unjail) = calculate_validators(deps.as_ref(), &env)?;

// update operators list with info about whether or not they're active validators
let ops: Vec<_> = operators()
.keys(deps.storage, None, None, Order::Ascending)
.collect::<StdResult<_>>()?;
for op in ops {
let active = validators.iter().any(|val| val.operator == op);
operators().update::<_, StdError>(deps.storage, &op, |op| {
let mut op = op.ok_or_else(|| StdError::generic_err("operator doesn't exist"))?;
op.active_validator = active;
Ok(op)
})?;
}

// auto unjailing
for addr in &auto_unjail {
JAIL.remove(deps.storage, addr)
Expand All @@ -559,7 +546,27 @@ fn end_block(deps: DepsMut, env: Env) -> Result<Response, ContractError> {
let old_validators = VALIDATORS.load(deps.storage)?;
VALIDATORS.save(deps.storage, &validators)?;
// determine the diff to send back to tendermint
let (diff, update_members) = calculate_diff(validators, old_validators);
let (diff, add, remove) = calculate_diff(validators, old_validators);
let update_members = RewardsDistribution::UpdateMembers {
add: add.clone(),
remove: remove.clone(),
};

// update operators list with info about whether or not they're active validators
for op in add {
operators().update::<_, StdError>(deps.storage, &Addr::unchecked(op.addr), |op| {
let mut op = op.ok_or_else(|| StdError::generic_err("operator doesn't exist"))?;
op.active_validator = true;
Ok(op)
})?;
}
for op in remove {
operators().update::<_, StdError>(deps.storage, &Addr::unchecked(op), |op| {
let mut op = op.ok_or_else(|| StdError::generic_err("operator doesn't exist"))?;
op.active_validator = false;
Ok(op)
})?;
}

// Store starting heights of new validators
match &update_members {
Expand Down Expand Up @@ -688,7 +695,7 @@ fn calculate_validators(
fn calculate_diff(
cur_vals: Vec<ValidatorInfo>,
old_vals: Vec<ValidatorInfo>,
) -> (ValidatorDiff, RewardsDistribution) {
) -> (ValidatorDiff, Vec<Member>, Vec<String>) {
// Compute additions and updates
let cur: BTreeSet<_> = cur_vals.iter().collect();
let old: BTreeSet<_> = old_vals.iter().collect();
Expand Down Expand Up @@ -734,10 +741,7 @@ fn calculate_diff(
// Compute, map and append removals to diffs
diffs.extend(removed_diff);

(
ValidatorDiff { diffs },
RewardsDistribution::UpdateMembers { add, remove },
)
(ValidatorDiff { diffs }, add, remove)
}

#[cfg_attr(not(feature = "library"), entry_point)]
Expand Down Expand Up @@ -902,16 +906,14 @@ mod test {
vals
}

fn update_members_msg(remove: Vec<&str>, add: Vec<(&str, u64)>) -> RewardsDistribution {
let remove = remove.into_iter().map(str::to_owned).collect();
let add = add
fn members(members: Vec<(&str, u64)>) -> Vec<Member> {
members
.into_iter()
.map(|(addr, weight)| Member {
addr: addr.to_owned(),
weight,
})
.collect();
RewardsDistribution::UpdateMembers { add, remove }
.collect()
}

// Unit tests for calculate_diff()
Expand Down Expand Up @@ -948,12 +950,12 @@ mod test {
];

// diff with itself must be empty
let (diff, update_members) = calculate_diff(vals.clone(), vals.clone());
let (diff, add, remove) = calculate_diff(vals.clone(), vals.clone());
assert_eq!(diff.diffs, vec![]);
assert_eq!(update_members, update_members_msg(vec![], vec! {}));
assert_eq!((add, remove), (vec![], vec![]));

// diff with empty must be itself (additions)
let (diff, update_members) = calculate_diff(vals.clone(), empty.clone());
let (diff, add, remove) = calculate_diff(vals.clone(), empty.clone());
assert_eq!(
vec![
ValidatorUpdate {
Expand All @@ -967,13 +969,11 @@ mod test {
],
diff.diffs
);
assert_eq!(
update_members,
update_members_msg(vec![], vec![("op1", 1), ("op2", 2)])
);
assert!(remove.is_empty());
assert_eq!(add, members(vec![("op1", 1), ("op2", 2)]));

// diff between empty and vals must be removals
let (diff, update_members) = calculate_diff(empty, vals.clone());
let (diff, add, remove) = calculate_diff(empty, vals.clone());
assert_eq!(
vec![
ValidatorUpdate {
Expand All @@ -987,10 +987,8 @@ mod test {
],
diff.diffs
);
assert_eq!(
update_members,
update_members_msg(vec!["op1", "op2"], vec![])
);
assert!(add.is_empty());
assert_eq!(remove, ["op1", "op2"]);

// Add a new member
let mut cur = vals.clone();
Expand All @@ -1008,56 +1006,59 @@ mod test {
});

// diff must be add last
let (diff, update_members) = calculate_diff(cur, vals.clone());
let (diff, add, remove) = calculate_diff(cur, vals.clone());
assert_eq!(
vec![ValidatorUpdate {
pubkey: Pubkey::Ed25519(b"pubkey3".into()),
power: 3
},],
diff.diffs
);
assert_eq!(update_members, update_members_msg(vec![], vec![("op3", 3)]));
assert!(remove.is_empty());
assert_eq!(add, members(vec![("op3", 3)]));

// add all but (one) last member
let old: Vec<_> = vals.iter().skip(1).cloned().collect();

// diff must be add all but last
let (diff, update_members) = calculate_diff(vals.clone(), old);
let (diff, add, remove) = calculate_diff(vals.clone(), old);
assert_eq!(
vec![ValidatorUpdate {
pubkey: Pubkey::Ed25519(b"pubkey1".into()),
power: 1
},],
diff.diffs
);
assert_eq!(update_members, update_members_msg(vec![], vec![("op1", 1)]));
assert!(remove.is_empty());
assert_eq!(add, members(vec![("op1", 1)]));

// remove last member
let cur: Vec<_> = vals.iter().take(1).cloned().collect();
// diff must be remove last
let (diff, update_members) = calculate_diff(cur, vals.clone());
let (diff, add, remove) = calculate_diff(cur, vals.clone());
assert_eq!(
vec![ValidatorUpdate {
pubkey: Pubkey::Ed25519(b"pubkey2".into()),
power: 0
},],
diff.diffs
);
assert_eq!(update_members, update_members_msg(vec!["op2"], vec![]));
assert!(add.is_empty());
assert_eq!(remove, ["op2"]);

// remove all but last member
let cur: Vec<_> = vals.iter().skip(1).cloned().collect();
// diff must be remove all but last
let (diff, update_members) = calculate_diff(cur, vals);
let (diff, add, remove) = calculate_diff(cur, vals);
assert_eq!(
vec![ValidatorUpdate {
pubkey: Pubkey::Ed25519(b"pubkey1".into()),
power: 0
},],
diff.diffs
);

assert_eq!(update_members, update_members_msg(vec!["op1"], vec![]));
assert!(add.is_empty());
assert_eq!(remove, ["op1"]);
}

// TODO: Another 7 in 1 test to be split
Expand All @@ -1067,12 +1068,13 @@ mod test {
let vals = validators(VALIDATORS);

// diff with itself must be empty
let (diff, update_members) = calculate_diff(vals.clone(), vals.clone());
let (diff, add, remove) = calculate_diff(vals.clone(), vals.clone());
assert_eq!(diff.diffs, vec![]);
assert_eq!(update_members, update_members_msg(vec![], vec![]));
assert!(add.is_empty());
assert!(remove.is_empty());

// diff with empty must be itself (additions)
let (diff, update_members) = calculate_diff(vals.clone(), empty.clone());
let (diff, add, remove) = calculate_diff(vals.clone(), empty.clone());
assert_eq!(
ValidatorDiff {
diffs: vals
Expand All @@ -1085,18 +1087,18 @@ mod test {
},
diff
);
assert!(remove.is_empty());
assert_eq!(
update_members,
update_members_msg(
vec![],
add,
members(
vals.iter()
.map(|vi| (vi.operator.as_str(), vi.power))
.collect()
)
);

// diff between empty and vals must be removals
let (diff, update_members) = calculate_diff(empty, vals.clone());
let (diff, add, remove) = calculate_diff(empty, vals.clone());
assert_eq!(
ValidatorDiff {
diffs: vals
Expand All @@ -1109,16 +1111,19 @@ mod test {
},
diff
);
assert!(add.is_empty());
assert_eq!(
update_members,
update_members_msg(vals.iter().map(|vi| vi.operator.as_str()).collect(), vec![])
remove,
vals.iter()
.map(|vi| vi.operator.as_str())
.collect::<Vec<_>>()
);

// Add a new member
let cur = validators(VALIDATORS + 1);

// diff must be add last
let (diff, update_members) = calculate_diff(cur.clone(), vals.clone());
let (diff, add, remove) = calculate_diff(cur.clone(), vals.clone());
assert_eq!(
ValidatorDiff {
diffs: vec![ValidatorUpdate {
Expand All @@ -1128,22 +1133,20 @@ mod test {
},
diff
);
assert!(remove.is_empty());
assert_eq!(
update_members,
update_members_msg(
vec![],
vec![(
cur.last().as_ref().unwrap().operator.as_str(),
(VALIDATORS + 1) as u64
)]
)
add,
members(vec![(
cur.last().as_ref().unwrap().operator.as_str(),
(VALIDATORS + 1) as u64
)])
);

// add all but (one) last member
let old: Vec<_> = vals.iter().skip(VALIDATORS - 1).cloned().collect();

// diff must be add all but last
let (diff, update_members) = calculate_diff(vals.clone(), old);
let (diff, add, remove) = calculate_diff(vals.clone(), old);
assert_eq!(
ValidatorDiff {
diffs: vals
Expand All @@ -1157,10 +1160,10 @@ mod test {
},
diff
);
assert!(remove.is_empty());
assert_eq!(
update_members,
update_members_msg(
vec![],
add,
members(
vals.iter()
.take(VALIDATORS - 1)
.map(|vi| (vi.operator.as_ref(), vi.power))
Expand All @@ -1171,7 +1174,7 @@ mod test {
// remove last member
let cur: Vec<_> = vals.iter().take(VALIDATORS - 1).cloned().collect();
// diff must be remove last
let (diff, update_members) = calculate_diff(cur, vals.clone());
let (diff, add, remove) = calculate_diff(cur, vals.clone());
assert_eq!(
ValidatorDiff {
diffs: vec![ValidatorUpdate {
Expand All @@ -1181,15 +1184,13 @@ mod test {
},
diff
);
assert_eq!(
update_members,
update_members_msg(vec![vals.last().unwrap().operator.as_ref()], vec![])
);
assert!(add.is_empty());
assert_eq!(remove, vec![vals.last().unwrap().operator.as_ref()]);

// remove all but last member
let cur: Vec<_> = vals.iter().skip(VALIDATORS - 1).cloned().collect();
// diff must be remove all but last
let (diff, update_members) = calculate_diff(cur, vals.clone());
let (diff, add, remove) = calculate_diff(cur, vals.clone());
assert_eq!(
ValidatorDiff {
diffs: vals
Expand All @@ -1203,15 +1204,13 @@ mod test {
},
diff
);
assert!(add.is_empty());
assert_eq!(
update_members,
update_members_msg(
vals.iter()
.take(VALIDATORS - 1)
.map(|vi| vi.operator.as_ref())
.collect(),
vec![]
)
remove,
vals.iter()
.take(VALIDATORS - 1)
.map(|vi| vi.operator.as_ref())
.collect::<Vec<_>>()
);
}
}

0 comments on commit e0f4667

Please sign in to comment.