Add untested validator change code
This commit is contained in:
parent
cc28b7370d
commit
a170bfe4fc
@ -43,6 +43,7 @@ members = [
|
|||||||
"beacon_chain/utils/ssz_helpers",
|
"beacon_chain/utils/ssz_helpers",
|
||||||
"beacon_chain/utils/vec_shuffle",
|
"beacon_chain/utils/vec_shuffle",
|
||||||
"beacon_chain/validation",
|
"beacon_chain/validation",
|
||||||
|
"beacon_chain/validator_change",
|
||||||
"beacon_chain/validator_induction",
|
"beacon_chain/validator_induction",
|
||||||
"beacon_chain/validator_shuffling",
|
"beacon_chain/validator_shuffling",
|
||||||
"lighthouse/db",
|
"lighthouse/db",
|
||||||
|
10
beacon_chain/validator_change/Cargo.toml
Normal file
10
beacon_chain/validator_change/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "validator_change"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
active-validators = { path = "../utils/active-validators" }
|
||||||
|
bytes = "0.4.10"
|
||||||
|
hashing = { path = "../utils/hashing" }
|
||||||
|
types = { path = "../types" }
|
148
beacon_chain/validator_change/src/lib.rs
Normal file
148
beacon_chain/validator_change/src/lib.rs
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
extern crate active_validators;
|
||||||
|
extern crate bytes;
|
||||||
|
extern crate hashing;
|
||||||
|
extern crate types;
|
||||||
|
|
||||||
|
use active_validators::validator_is_active;
|
||||||
|
use bytes::{
|
||||||
|
BytesMut,
|
||||||
|
BufMut,
|
||||||
|
};
|
||||||
|
use hashing::canonical_hash;
|
||||||
|
use std::cmp::max;
|
||||||
|
use types::{
|
||||||
|
Hash256,
|
||||||
|
ValidatorRecord,
|
||||||
|
ValidatorStatus,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub enum UpdateValidatorSetError {
|
||||||
|
ArithmeticOverflow,
|
||||||
|
}
|
||||||
|
|
||||||
|
const VALIDATOR_FLAG_ENTRY: u8 = 0;
|
||||||
|
const VALIDATOR_FLAG_EXIT: u8 = 1;
|
||||||
|
|
||||||
|
pub fn update_validator_set(
|
||||||
|
validators: &mut Vec<ValidatorRecord>,
|
||||||
|
hash_chain: Hash256,
|
||||||
|
present_slot: u64,
|
||||||
|
deposit_size_gwei: u64,
|
||||||
|
max_validator_churn_quotient: u64)
|
||||||
|
-> Result<(), UpdateValidatorSetError>
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Total balance of all active validators.
|
||||||
|
*
|
||||||
|
* Return an error if an overflow occurs.
|
||||||
|
*/
|
||||||
|
let total_balance = {
|
||||||
|
let mut bal: u64 = 0;
|
||||||
|
for v in validators.iter() {
|
||||||
|
if validator_is_active(&v) {
|
||||||
|
bal = bal.checked_add(v.balance)
|
||||||
|
.ok_or(UpdateValidatorSetError::ArithmeticOverflow)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bal
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: this is not the maximum allowable change, it can actually be higher.
|
||||||
|
*/
|
||||||
|
let max_allowable_change = {
|
||||||
|
let double_deposit_size = deposit_size_gwei.checked_mul(2)
|
||||||
|
.ok_or(UpdateValidatorSetError::ArithmeticOverflow)?;
|
||||||
|
max(double_deposit_size, total_balance / max_validator_churn_quotient)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut hasher = ValidatorChangeHashChain {
|
||||||
|
bytes: hash_chain.to_vec(),
|
||||||
|
};
|
||||||
|
let mut total_changed: u64 = 0;
|
||||||
|
for (i, v) in validators.iter_mut().enumerate() {
|
||||||
|
match v.status {
|
||||||
|
/*
|
||||||
|
* Validator is pending activiation.
|
||||||
|
*/
|
||||||
|
x if x == ValidatorStatus::PendingActivation as u8 => {
|
||||||
|
let new_total_changed = total_changed.checked_add(deposit_size_gwei)
|
||||||
|
.ok_or(UpdateValidatorSetError::ArithmeticOverflow)?;
|
||||||
|
/*
|
||||||
|
* If entering this validator would not exceed the max balance delta,
|
||||||
|
* activate the validator.
|
||||||
|
*/
|
||||||
|
if new_total_changed <= max_allowable_change {
|
||||||
|
v.status = ValidatorStatus::Active as u8;
|
||||||
|
hasher.extend(i, &v.pubkey.as_bytes(), VALIDATOR_FLAG_ENTRY);
|
||||||
|
total_changed = new_total_changed;
|
||||||
|
} else {
|
||||||
|
// Entering the validator would exceed the balance delta.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Validator is pending exit.
|
||||||
|
*/
|
||||||
|
x if x == ValidatorStatus::PendingExit as u8 => {
|
||||||
|
let new_total_changed = total_changed.checked_add(v.balance)
|
||||||
|
.ok_or(UpdateValidatorSetError::ArithmeticOverflow)?;
|
||||||
|
/*
|
||||||
|
* If exiting this validator would not exceed the max balance delta,
|
||||||
|
* exit the validator
|
||||||
|
*/
|
||||||
|
if new_total_changed <= max_allowable_change {
|
||||||
|
v.status = ValidatorStatus::PendingWithdraw as u8;
|
||||||
|
v.exit_slot = present_slot;
|
||||||
|
hasher.extend(i, &v.pubkey.as_bytes(), VALIDATOR_FLAG_EXIT);
|
||||||
|
total_changed = new_total_changed;
|
||||||
|
} else {
|
||||||
|
// Exiting the validator would exceed the balance delta.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
};
|
||||||
|
if total_changed >= max_allowable_change {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ValidatorChangeHashChain {
|
||||||
|
bytes: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ValidatorChangeHashChain {
|
||||||
|
pub fn extend(&mut self, index: usize, pubkey: &Vec<u8>, flag: u8)
|
||||||
|
{
|
||||||
|
let mut message = self.bytes.clone();
|
||||||
|
message.append(&mut serialize_validator_change_record(index, pubkey, flag));
|
||||||
|
self.bytes = canonical_hash(&message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_validator_change_record(index: usize, pubkey: &Vec<u8>, flag: u8)
|
||||||
|
-> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut buf = BytesMut::with_capacity(68);
|
||||||
|
buf.put_u8(flag);
|
||||||
|
let index_bytes = {
|
||||||
|
let mut buf = BytesMut::with_capacity(8);
|
||||||
|
buf.put_u64_be(index as u64);
|
||||||
|
buf.take()[8 - 3..8].to_vec()
|
||||||
|
};
|
||||||
|
buf.put(index_bytes);
|
||||||
|
buf.put(pubkey);
|
||||||
|
buf.take().to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
assert_eq!(2 + 2, 4);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user