Merge branch 'master' into validator-record-update
This commit is contained in:
commit
8974d8e1df
@ -38,7 +38,6 @@ members = [
|
|||||||
"beacon_chain/spec",
|
"beacon_chain/spec",
|
||||||
"beacon_chain/state-transition",
|
"beacon_chain/state-transition",
|
||||||
"beacon_chain/types",
|
"beacon_chain/types",
|
||||||
"beacon_chain/utils/active-validators",
|
|
||||||
"beacon_chain/utils/bls",
|
"beacon_chain/utils/bls",
|
||||||
"beacon_chain/utils/boolean-bitfield",
|
"beacon_chain/utils/boolean-bitfield",
|
||||||
"beacon_chain/utils/hashing",
|
"beacon_chain/utils/hashing",
|
||||||
|
@ -1,14 +1,29 @@
|
|||||||
use super::bls::{Keypair, PublicKey};
|
use super::bls::{Keypair, PublicKey};
|
||||||
use super::{Hash256};
|
use super::{Hash256};
|
||||||
|
use std::convert;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum ValidatorStatus {
|
pub enum ValidatorStatus {
|
||||||
PendingActivation = 0,
|
PendingActivation,
|
||||||
Active = 1,
|
Active,
|
||||||
PendingExit = 2,
|
PendingExit,
|
||||||
PendingWithdraw = 3,
|
PendingWithdraw,
|
||||||
Withdrawn = 5,
|
Withdrawn,
|
||||||
Penalized = 127,
|
Penalized,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl convert::From<u8> for ValidatorStatus {
|
||||||
|
fn from(status: u8) -> Self {
|
||||||
|
match status {
|
||||||
|
0 => ValidatorStatus::PendingActivation,
|
||||||
|
1 => ValidatorStatus::Active,
|
||||||
|
2 => ValidatorStatus::PendingExit,
|
||||||
|
3 => ValidatorStatus::PendingWithdraw,
|
||||||
|
5 => ValidatorStatus::Withdrawn,
|
||||||
|
127 => ValidatorStatus::Penalized,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
@ -42,6 +57,10 @@ impl ValidatorRecord {
|
|||||||
};
|
};
|
||||||
(s, keypair)
|
(s, keypair)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn status_is(&self, status: ValidatorStatus) -> bool {
|
||||||
|
self.status == status
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "active-validators"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
types = { path = "../../types" }
|
|
@ -1,63 +0,0 @@
|
|||||||
extern crate types;
|
|
||||||
|
|
||||||
use types::{ValidatorRecord, ValidatorStatus};
|
|
||||||
|
|
||||||
pub fn validator_is_active(v: &ValidatorRecord) -> bool {
|
|
||||||
v.status == ValidatorStatus::Active as u8
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the indicies of each active validator in a given vec of validators.
|
|
||||||
pub fn active_validator_indices(validators: &[ValidatorRecord]) -> Vec<usize> {
|
|
||||||
validators
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.filter_map(|(i, validator)| {
|
|
||||||
if validator_is_active(&validator) {
|
|
||||||
Some(i)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}).collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_active_validator() {
|
|
||||||
let mut validators = vec![];
|
|
||||||
|
|
||||||
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
|
||||||
v.status = ValidatorStatus::Active as u8;
|
|
||||||
assert!(validator_is_active(&v));
|
|
||||||
validators.push(v);
|
|
||||||
|
|
||||||
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
|
||||||
v.status = ValidatorStatus::PendingActivation as u8;
|
|
||||||
assert!(!validator_is_active(&v));
|
|
||||||
validators.push(v);
|
|
||||||
|
|
||||||
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
|
||||||
v.status = ValidatorStatus::PendingExit as u8;
|
|
||||||
assert!(!validator_is_active(&v));
|
|
||||||
validators.push(v);
|
|
||||||
|
|
||||||
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
|
||||||
v.status = ValidatorStatus::PendingWithdraw as u8;
|
|
||||||
assert!(!validator_is_active(&v));
|
|
||||||
validators.push(v);
|
|
||||||
|
|
||||||
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
|
||||||
v.status = ValidatorStatus::Withdrawn as u8;
|
|
||||||
assert!(!validator_is_active(&v));
|
|
||||||
validators.push(v);
|
|
||||||
|
|
||||||
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
|
||||||
v.status = ValidatorStatus::Penalized as u8;
|
|
||||||
assert!(!validator_is_active(&v));
|
|
||||||
validators.push(v);
|
|
||||||
|
|
||||||
assert_eq!(active_validator_indices(&validators), vec![0]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,6 @@ version = "0.1.0"
|
|||||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
active-validators = { path = "../utils/active-validators" }
|
|
||||||
bytes = "0.4.10"
|
bytes = "0.4.10"
|
||||||
hashing = { path = "../utils/hashing" }
|
hashing = { path = "../utils/hashing" }
|
||||||
types = { path = "../types" }
|
types = { path = "../types" }
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
extern crate active_validators;
|
|
||||||
extern crate bytes;
|
extern crate bytes;
|
||||||
extern crate hashing;
|
extern crate hashing;
|
||||||
extern crate types;
|
extern crate types;
|
||||||
|
|
||||||
use active_validators::validator_is_active;
|
|
||||||
use bytes::{BufMut, BytesMut};
|
use bytes::{BufMut, BytesMut};
|
||||||
use hashing::canonical_hash;
|
use hashing::canonical_hash;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
@ -31,7 +29,7 @@ pub fn update_validator_set(
|
|||||||
let total_balance = {
|
let total_balance = {
|
||||||
let mut bal: u64 = 0;
|
let mut bal: u64 = 0;
|
||||||
for v in validators.iter() {
|
for v in validators.iter() {
|
||||||
if validator_is_active(&v) {
|
if v.status_is(ValidatorStatus::Active) {
|
||||||
bal = bal
|
bal = bal
|
||||||
.checked_add(v.balance)
|
.checked_add(v.balance)
|
||||||
.ok_or(UpdateValidatorSetError::ArithmeticOverflow)?;
|
.ok_or(UpdateValidatorSetError::ArithmeticOverflow)?;
|
||||||
@ -62,7 +60,7 @@ pub fn update_validator_set(
|
|||||||
/*
|
/*
|
||||||
* Validator is pending activiation.
|
* Validator is pending activiation.
|
||||||
*/
|
*/
|
||||||
x if x == ValidatorStatus::PendingActivation as u8 => {
|
ValidatorStatus::PendingActivation => {
|
||||||
let new_total_changed = total_changed
|
let new_total_changed = total_changed
|
||||||
.checked_add(deposit_size_gwei)
|
.checked_add(deposit_size_gwei)
|
||||||
.ok_or(UpdateValidatorSetError::ArithmeticOverflow)?;
|
.ok_or(UpdateValidatorSetError::ArithmeticOverflow)?;
|
||||||
@ -71,7 +69,7 @@ pub fn update_validator_set(
|
|||||||
* activate the validator.
|
* activate the validator.
|
||||||
*/
|
*/
|
||||||
if new_total_changed <= max_allowable_change {
|
if new_total_changed <= max_allowable_change {
|
||||||
v.status = ValidatorStatus::Active as u8;
|
v.status = ValidatorStatus::Active;
|
||||||
hasher.extend(i, &v.pubkey.as_bytes(), VALIDATOR_FLAG_ENTRY);
|
hasher.extend(i, &v.pubkey.as_bytes(), VALIDATOR_FLAG_ENTRY);
|
||||||
total_changed = new_total_changed;
|
total_changed = new_total_changed;
|
||||||
} else {
|
} else {
|
||||||
@ -82,7 +80,7 @@ pub fn update_validator_set(
|
|||||||
/*
|
/*
|
||||||
* Validator is pending exit.
|
* Validator is pending exit.
|
||||||
*/
|
*/
|
||||||
x if x == ValidatorStatus::PendingExit as u8 => {
|
ValidatorStatus::PendingExit => {
|
||||||
let new_total_changed = total_changed
|
let new_total_changed = total_changed
|
||||||
.checked_add(v.balance)
|
.checked_add(v.balance)
|
||||||
.ok_or(UpdateValidatorSetError::ArithmeticOverflow)?;
|
.ok_or(UpdateValidatorSetError::ArithmeticOverflow)?;
|
||||||
@ -91,7 +89,7 @@ pub fn update_validator_set(
|
|||||||
* exit the validator
|
* exit the validator
|
||||||
*/
|
*/
|
||||||
if new_total_changed <= max_allowable_change {
|
if new_total_changed <= max_allowable_change {
|
||||||
v.status = ValidatorStatus::PendingWithdraw as u8;
|
v.status = ValidatorStatus::PendingWithdraw;
|
||||||
v.exit_slot = present_slot;
|
v.exit_slot = present_slot;
|
||||||
hasher.extend(i, &v.pubkey.as_bytes(), VALIDATOR_FLAG_EXIT);
|
hasher.extend(i, &v.pubkey.as_bytes(), VALIDATOR_FLAG_EXIT);
|
||||||
total_changed = new_total_changed;
|
total_changed = new_total_changed;
|
||||||
|
@ -68,7 +68,7 @@ impl ValidatorInductor {
|
|||||||
randao_commitment: r.randao_commitment,
|
randao_commitment: r.randao_commitment,
|
||||||
randao_last_change: self.current_slot,
|
randao_last_change: self.current_slot,
|
||||||
balance: DEPOSIT_GWEI,
|
balance: DEPOSIT_GWEI,
|
||||||
status: status as u8,
|
status: status,
|
||||||
exit_slot: 0,
|
exit_slot: 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ impl ValidatorInductor {
|
|||||||
/// `validator.status == Withdrawn`. If no such record exists, `None` is returned.
|
/// `validator.status == Withdrawn`. If no such record exists, `None` is returned.
|
||||||
fn first_withdrawn_validator(&mut self) -> Option<usize> {
|
fn first_withdrawn_validator(&mut self) -> Option<usize> {
|
||||||
for i in self.empty_validator_start..self.validators.len() {
|
for i in self.empty_validator_start..self.validators.len() {
|
||||||
if self.validators[i].status == ValidatorStatus::Withdrawn as u8 {
|
if self.validators[i].status == ValidatorStatus::Withdrawn {
|
||||||
self.empty_validator_start = i + 1;
|
self.empty_validator_start = i + 1;
|
||||||
return Some(i);
|
return Some(i);
|
||||||
}
|
}
|
||||||
@ -166,8 +166,8 @@ mod tests {
|
|||||||
let _ = inductor.induct(&r, ValidatorStatus::Active);
|
let _ = inductor.induct(&r, ValidatorStatus::Active);
|
||||||
let validators = inductor.to_vec();
|
let validators = inductor.to_vec();
|
||||||
|
|
||||||
assert!(validators[0].status == ValidatorStatus::PendingActivation as u8);
|
assert!(validators[0].status == ValidatorStatus::PendingActivation);
|
||||||
assert!(validators[1].status == ValidatorStatus::Active as u8);
|
assert!(validators[1].status == ValidatorStatus::Active);
|
||||||
assert_eq!(validators.len(), 2);
|
assert_eq!(validators.len(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +176,7 @@ mod tests {
|
|||||||
let mut validators = vec![];
|
let mut validators = vec![];
|
||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
||||||
v.status = ValidatorStatus::Active as u8;
|
v.status = ValidatorStatus::Active;
|
||||||
validators.push(v);
|
validators.push(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,11 +195,11 @@ mod tests {
|
|||||||
fn test_validator_inductor_valid_all_second_validator_withdrawn() {
|
fn test_validator_inductor_valid_all_second_validator_withdrawn() {
|
||||||
let mut validators = vec![];
|
let mut validators = vec![];
|
||||||
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
||||||
v.status = ValidatorStatus::Active as u8;
|
v.status = ValidatorStatus::Active;
|
||||||
validators.push(v);
|
validators.push(v);
|
||||||
for _ in 0..4 {
|
for _ in 0..4 {
|
||||||
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
||||||
v.status = ValidatorStatus::Withdrawn as u8;
|
v.status = ValidatorStatus::Withdrawn;
|
||||||
validators.push(v);
|
validators.push(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ mod tests {
|
|||||||
let mut validators = vec![];
|
let mut validators = vec![];
|
||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
|
||||||
v.status = ValidatorStatus::Withdrawn as u8;
|
v.status = ValidatorStatus::Withdrawn;
|
||||||
validators.push(v);
|
validators.push(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ version = "0.1.0"
|
|||||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
active-validators = { path = "../utils/active-validators" }
|
|
||||||
honey-badger-split = { path = "../utils/honey-badger-split" }
|
honey-badger-split = { path = "../utils/honey-badger-split" }
|
||||||
types = { path = "../types" }
|
types = { path = "../types" }
|
||||||
vec_shuffle = { path = "../utils/vec_shuffle" }
|
vec_shuffle = { path = "../utils/vec_shuffle" }
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
extern crate active_validators;
|
|
||||||
extern crate honey_badger_split;
|
extern crate honey_badger_split;
|
||||||
extern crate types;
|
extern crate types;
|
||||||
extern crate vec_shuffle;
|
extern crate vec_shuffle;
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
||||||
use active_validators::active_validator_indices;
|
|
||||||
use honey_badger_split::SplitExt;
|
use honey_badger_split::SplitExt;
|
||||||
use types::{ChainConfig, ShardAndCommittee, ValidatorRecord};
|
use types::{ChainConfig, ShardAndCommittee, ValidatorRecord, ValidatorStatus};
|
||||||
use vec_shuffle::{shuffle, ShuffleErr};
|
use vec_shuffle::{shuffle, ShuffleErr};
|
||||||
|
|
||||||
type DelegatedCycle = Vec<Vec<ShardAndCommittee>>;
|
type DelegatedCycle = Vec<Vec<ShardAndCommittee>>;
|
||||||
@ -24,7 +23,17 @@ pub fn shard_and_committees_for_cycle(
|
|||||||
config: &ChainConfig,
|
config: &ChainConfig,
|
||||||
) -> Result<DelegatedCycle, ValidatorAssignmentError> {
|
) -> Result<DelegatedCycle, ValidatorAssignmentError> {
|
||||||
let shuffled_validator_indices = {
|
let shuffled_validator_indices = {
|
||||||
let mut validator_indices = active_validator_indices(validators);
|
let mut validator_indices = validators
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(i, validator)| {
|
||||||
|
if validator.status_is(ValidatorStatus::Active) {
|
||||||
|
Some(i)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
shuffle(seed, validator_indices)?
|
shuffle(seed, validator_indices)?
|
||||||
};
|
};
|
||||||
let shard_indices: Vec<usize> = (0_usize..config.shard_count as usize).into_iter().collect();
|
let shard_indices: Vec<usize> = (0_usize..config.shard_count as usize).into_iter().collect();
|
||||||
@ -87,8 +96,10 @@ fn generate_cycle(
|
|||||||
.map(|(j, shard_indices)| ShardAndCommittee {
|
.map(|(j, shard_indices)| ShardAndCommittee {
|
||||||
shard: ((shard_start + j) % shard_count) as u16,
|
shard: ((shard_start + j) % shard_count) as u16,
|
||||||
committee: shard_indices.to_vec(),
|
committee: shard_indices.to_vec(),
|
||||||
}).collect()
|
})
|
||||||
}).collect();
|
.collect()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
Ok(cycle)
|
Ok(cycle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user